mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: allow multiple SSA block control values
Control values are used to choose which successor of a block is jumped to. Typically a control value takes the form of a 'flags' value that represents the result of a comparison. Some architectures however use a variable in a register as a control value. Up until now we have managed with a single control value per block. However some architectures (e.g. s390x and riscv64) have combined compare-and-branch instructions that take two variables in registers as parameters. To generate these instructions we need to support 2 control values per block. This CL allows up to 2 control values to be used in a block in order to support the addition of compare-and-branch instructions. I have implemented s390x compare-and-branch instructions in a different CL. Passes toolstash-check -all. Results of compilebench: name old time/op new time/op delta Template 208ms ± 1% 209ms ± 1% ~ (p=0.289 n=20+20) Unicode 83.7ms ± 1% 83.3ms ± 3% -0.49% (p=0.017 n=18+18) GoTypes 748ms ± 1% 748ms ± 0% ~ (p=0.460 n=20+18) Compiler 3.47s ± 1% 3.48s ± 1% ~ (p=0.070 n=19+18) SSA 11.5s ± 1% 11.7s ± 1% +1.64% (p=0.000 n=19+18) Flate 130ms ± 1% 130ms ± 1% ~ (p=0.588 n=19+20) GoParser 160ms ± 1% 161ms ± 1% ~ (p=0.211 n=20+20) Reflect 465ms ± 1% 467ms ± 1% +0.42% (p=0.007 n=20+20) Tar 184ms ± 1% 185ms ± 2% ~ (p=0.087 n=18+20) XML 253ms ± 1% 253ms ± 1% ~ (p=0.377 n=20+18) LinkCompiler 769ms ± 2% 774ms ± 2% ~ (p=0.070 n=19+19) ExternalLinkCompiler 3.59s ±11% 3.68s ± 6% ~ (p=0.072 n=20+20) LinkWithoutDebugCompiler 446ms ± 5% 454ms ± 3% +1.79% (p=0.002 n=19+20) StdCmd 26.0s ± 2% 26.0s ± 2% ~ (p=0.799 n=20+20) name old user-time/op new user-time/op delta Template 238ms ± 5% 240ms ± 5% ~ (p=0.142 n=20+20) Unicode 105ms ±11% 106ms ±10% ~ (p=0.512 n=20+20) GoTypes 876ms ± 2% 873ms ± 4% ~ (p=0.647 n=20+19) Compiler 4.17s ± 2% 4.19s ± 1% ~ (p=0.093 n=20+18) SSA 13.9s ± 1% 14.1s ± 1% +1.45% (p=0.000 n=18+18) Flate 145ms ±13% 146ms ± 5% ~ (p=0.851 n=20+18) GoParser 185ms ± 5% 188ms ± 7% ~ (p=0.174 n=20+20) Reflect 534ms ± 3% 538ms ± 2% ~ (p=0.105 n=20+18) Tar 215ms ± 4% 211ms ± 9% ~ (p=0.079 n=19+20) XML 295ms ± 6% 295ms ± 5% ~ (p=0.968 n=20+20) LinkCompiler 832ms ± 4% 837ms ± 7% ~ (p=0.707 n=17+20) ExternalLinkCompiler 1.58s ± 8% 1.60s ± 4% ~ (p=0.296 n=20+19) LinkWithoutDebugCompiler 478ms ±12% 489ms ±10% ~ (p=0.429 n=20+20) name old object-bytes new object-bytes delta Template 559kB ± 0% 559kB ± 0% ~ (all equal) Unicode 216kB ± 0% 216kB ± 0% ~ (all equal) GoTypes 2.03MB ± 0% 2.03MB ± 0% ~ (all equal) Compiler 8.07MB ± 0% 8.07MB ± 0% -0.06% (p=0.000 n=20+20) SSA 27.1MB ± 0% 27.3MB ± 0% +0.89% (p=0.000 n=20+20) Flate 343kB ± 0% 343kB ± 0% ~ (all equal) GoParser 441kB ± 0% 441kB ± 0% ~ (all equal) Reflect 1.36MB ± 0% 1.36MB ± 0% ~ (all equal) Tar 487kB ± 0% 487kB ± 0% ~ (all equal) XML 632kB ± 0% 632kB ± 0% ~ (all equal) name old export-bytes new export-bytes delta Template 18.5kB ± 0% 18.5kB ± 0% ~ (all equal) Unicode 7.92kB ± 0% 7.92kB ± 0% ~ (all equal) GoTypes 35.0kB ± 0% 35.0kB ± 0% ~ (all equal) Compiler 109kB ± 0% 110kB ± 0% +0.72% (p=0.000 n=20+20) SSA 137kB ± 0% 138kB ± 0% +0.58% (p=0.000 n=20+20) Flate 4.89kB ± 0% 4.89kB ± 0% ~ (all equal) GoParser 8.49kB ± 0% 8.49kB ± 0% ~ (all equal) Reflect 11.4kB ± 0% 11.4kB ± 0% ~ (all equal) Tar 10.5kB ± 0% 10.5kB ± 0% ~ (all equal) XML 16.7kB ± 0% 16.7kB ± 0% ~ (all equal) name old text-bytes new text-bytes delta HelloSize 761kB ± 0% 761kB ± 0% ~ (all equal) CmdGoSize 10.8MB ± 0% 10.8MB ± 0% ~ (all equal) name old data-bytes new data-bytes delta HelloSize 10.7kB ± 0% 10.7kB ± 0% ~ (all equal) CmdGoSize 312kB ± 0% 312kB ± 0% ~ (all equal) name old bss-bytes new bss-bytes delta HelloSize 122kB ± 0% 122kB ± 0% ~ (all equal) CmdGoSize 146kB ± 0% 146kB ± 0% ~ (all equal) name old exe-bytes new exe-bytes delta HelloSize 1.13MB ± 0% 1.13MB ± 0% ~ (all equal) CmdGoSize 15.1MB ± 0% 15.1MB ± 0% ~ (all equal) Change-Id: I3cc2f9829a109543d9a68be4a21775d2d3e9801f Reviewed-on: https://go-review.googlesource.com/c/go/+/196557 Run-TryBot: Michael Munday <mike.munday@ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Daniel Martí <mvdan@mvdan.cc> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
274f4cef93
commit
9c2e7e8bed
63 changed files with 6026 additions and 4579 deletions
|
|
@ -18,8 +18,8 @@ import (
|
|||
// markMoves marks any MOVXconst ops that need to avoid clobbering flags.
|
||||
func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) {
|
||||
flive := b.FlagsLiveAtEnd
|
||||
if b.Control != nil && b.Control.Type.IsFlags() {
|
||||
flive = true
|
||||
for _, c := range b.ControlValues() {
|
||||
flive = c.Type.IsFlags() || flive
|
||||
}
|
||||
for i := len(b.Values) - 1; i >= 0; i-- {
|
||||
v := b.Values[i]
|
||||
|
|
@ -1245,6 +1245,6 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
}
|
||||
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -955,6 +955,6 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
}
|
||||
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1057,9 +1057,9 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
s.Br(obj.AJMP, b.Succs[0].Block())
|
||||
}
|
||||
}
|
||||
if !b.Control.Type.IsFlags() {
|
||||
if !b.Controls[0].Type.IsFlags() {
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = b.Control.Reg()
|
||||
p.From.Reg = b.Controls[0].Reg()
|
||||
}
|
||||
case ssa.BlockARM64TBZ, ssa.BlockARM64TBNZ:
|
||||
jmp := blockJump[b.Kind]
|
||||
|
|
@ -1080,9 +1080,9 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
}
|
||||
p.From.Offset = b.Aux.(int64)
|
||||
p.From.Type = obj.TYPE_CONST
|
||||
p.Reg = b.Control.Reg()
|
||||
p.Reg = b.Controls[0].Reg()
|
||||
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -670,7 +670,7 @@ func (lv *Liveness) markUnsafePoints() {
|
|||
// single op that does the memory load from the flag
|
||||
// address, so we look for that.
|
||||
var load *ssa.Value
|
||||
v := wbBlock.Control
|
||||
v := wbBlock.Controls[0]
|
||||
for {
|
||||
if sym, ok := v.Aux.(*obj.LSym); ok && sym == writeBarrier {
|
||||
load = v
|
||||
|
|
|
|||
|
|
@ -855,11 +855,11 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
s.Br(obj.AJMP, b.Succs[0].Block())
|
||||
}
|
||||
}
|
||||
if !b.Control.Type.IsFlags() {
|
||||
if !b.Controls[0].Type.IsFlags() {
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = b.Control.Reg()
|
||||
p.From.Reg = b.Controls[0].Reg()
|
||||
}
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -829,11 +829,11 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
s.Br(obj.AJMP, b.Succs[0].Block())
|
||||
}
|
||||
}
|
||||
if !b.Control.Type.IsFlags() {
|
||||
if !b.Controls[0].Type.IsFlags() {
|
||||
p.From.Type = obj.TYPE_REG
|
||||
p.From.Reg = b.Control.Reg()
|
||||
p.From.Reg = b.Controls[0].Reg()
|
||||
}
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1337,6 +1337,6 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
}
|
||||
}
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ import (
|
|||
// markMoves marks any MOVXconst ops that need to avoid clobbering flags.
|
||||
func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) {
|
||||
flive := b.FlagsLiveAtEnd
|
||||
if b.Control != nil && b.Control.Type.IsFlags() {
|
||||
flive = true
|
||||
for _, c := range b.ControlValues() {
|
||||
flive = c.Type.IsFlags() || flive
|
||||
}
|
||||
for i := len(b.Values) - 1; i >= 0; i-- {
|
||||
v := b.Values[i]
|
||||
|
|
@ -864,6 +864,6 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
s.Br(s390x.ABR, succs[1])
|
||||
}
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,10 +82,10 @@ 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. Its control
|
||||
value 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.
|
||||
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:
|
||||
|
||||
|
|
|
|||
|
|
@ -40,23 +40,28 @@ type Block struct {
|
|||
// arguments by block id and have this field computed explicitly when needed?
|
||||
Preds []Edge
|
||||
|
||||
// A value that determines how the block is exited. Its value depends on the kind
|
||||
// of the block. For instance, a BlockIf has a boolean control value and BlockExit
|
||||
// has a memory control value.
|
||||
Control *Value
|
||||
// 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{}
|
||||
|
||||
// The unordered set of Values that define the operation of this block.
|
||||
// The list must include the control value, if any. (TODO: need this last condition?)
|
||||
// After the scheduling pass, this list is ordered.
|
||||
Values []*Value
|
||||
|
||||
// The containing function
|
||||
Func *Func
|
||||
|
||||
// Storage for Succs, Preds, and Values
|
||||
// Storage for Succs, Preds and Values.
|
||||
succstorage [2]Edge
|
||||
predstorage [4]Edge
|
||||
valstorage [9]*Value
|
||||
|
|
@ -96,12 +101,12 @@ func (e Edge) Index() int {
|
|||
return e.i
|
||||
}
|
||||
|
||||
// kind control successors
|
||||
// kind controls successors
|
||||
// ------------------------------------------
|
||||
// Exit return mem []
|
||||
// Plain nil [next]
|
||||
// If a boolean Value [then, else]
|
||||
// Defer mem [nopanic, panic] (control opcode should be OpStaticCall to runtime.deferproc)
|
||||
// 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
|
||||
|
|
@ -115,8 +120,8 @@ func (b *Block) LongString() string {
|
|||
if b.Aux != nil {
|
||||
s += fmt.Sprintf(" %s", b.Aux)
|
||||
}
|
||||
if b.Control != nil {
|
||||
s += fmt.Sprintf(" %s", b.Control)
|
||||
for _, c := range b.ControlValues() {
|
||||
s += fmt.Sprintf(" %s", c)
|
||||
}
|
||||
if len(b.Succs) > 0 {
|
||||
s += " ->"
|
||||
|
|
@ -133,13 +138,76 @@ func (b *Block) LongString() string {
|
|||
return s
|
||||
}
|
||||
|
||||
func (b *Block) SetControl(v *Value) {
|
||||
if w := b.Control; w != nil {
|
||||
w.Uses--
|
||||
// NumControls returns the number of non-nil control values the
|
||||
// block has.
|
||||
func (b *Block) NumControls() int {
|
||||
if b.Controls[0] == nil {
|
||||
return 0
|
||||
}
|
||||
b.Control = v
|
||||
if v != nil {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -160,13 +160,13 @@ func elimIf(f *Func, loadAddr *sparseSet, dom *Block) bool {
|
|||
if swap {
|
||||
v.Args[0], v.Args[1] = v.Args[1], v.Args[0]
|
||||
}
|
||||
v.AddArg(dom.Control)
|
||||
v.AddArg(dom.Controls[0])
|
||||
}
|
||||
|
||||
// Put all of the instructions into 'dom'
|
||||
// and update the CFG appropriately.
|
||||
dom.Kind = post.Kind
|
||||
dom.SetControl(post.Control)
|
||||
dom.CopyControls(post)
|
||||
dom.Aux = post.Aux
|
||||
dom.Succs = append(dom.Succs[:0], post.Succs...)
|
||||
for i := range dom.Succs {
|
||||
|
|
@ -201,7 +201,7 @@ func clobberBlock(b *Block) {
|
|||
b.Preds = nil
|
||||
b.Succs = nil
|
||||
b.Aux = nil
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Likely = BranchUnknown
|
||||
b.Kind = BlockInvalid
|
||||
}
|
||||
|
|
@ -259,13 +259,13 @@ func elimIfElse(f *Func, loadAddr *sparseSet, b *Block) bool {
|
|||
if swap {
|
||||
v.Args[0], v.Args[1] = v.Args[1], v.Args[0]
|
||||
}
|
||||
v.AddArg(b.Control)
|
||||
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.SetControl(post.Control)
|
||||
b.CopyControls(post)
|
||||
b.Aux = post.Aux
|
||||
b.Succs = append(b.Succs[:0], post.Succs...)
|
||||
for i := range b.Succs {
|
||||
|
|
|
|||
|
|
@ -39,31 +39,31 @@ func checkFunc(f *Func) {
|
|||
if len(b.Succs) != 0 {
|
||||
f.Fatalf("exit block %s has successors", b)
|
||||
}
|
||||
if b.Control == nil {
|
||||
if b.NumControls() != 1 {
|
||||
f.Fatalf("exit block %s has no control value", b)
|
||||
}
|
||||
if !b.Control.Type.IsMemory() {
|
||||
f.Fatalf("exit block %s has non-memory control value %s", b, b.Control.LongString())
|
||||
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.Control == nil {
|
||||
if b.NumControls() != 1 {
|
||||
f.Fatalf("ret block %s has nil control", b)
|
||||
}
|
||||
if !b.Control.Type.IsMemory() {
|
||||
f.Fatalf("ret block %s has non-memory control value %s", b, b.Control.LongString())
|
||||
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.Control == nil {
|
||||
if b.NumControls() != 1 {
|
||||
f.Fatalf("retjmp block %s has nil control", b)
|
||||
}
|
||||
if !b.Control.Type.IsMemory() {
|
||||
f.Fatalf("retjmp block %s has non-memory control value %s", b, b.Control.LongString())
|
||||
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)
|
||||
|
|
@ -72,34 +72,34 @@ func checkFunc(f *Func) {
|
|||
if len(b.Succs) != 1 {
|
||||
f.Fatalf("plain block %s len(Succs)==%d, want 1", b, len(b.Succs))
|
||||
}
|
||||
if b.Control != nil {
|
||||
f.Fatalf("plain block %s has non-nil control %s", b, b.Control.LongString())
|
||||
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.Control == nil {
|
||||
if b.NumControls() != 1 {
|
||||
f.Fatalf("if block %s has no control value", b)
|
||||
}
|
||||
if !b.Control.Type.IsBoolean() {
|
||||
f.Fatalf("if block %s has non-bool control value %s", b, b.Control.LongString())
|
||||
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.Control == nil {
|
||||
if b.NumControls() != 1 {
|
||||
f.Fatalf("defer block %s has no control value", b)
|
||||
}
|
||||
if !b.Control.Type.IsMemory() {
|
||||
f.Fatalf("defer block %s has non-memory control value %s", b, b.Control.LongString())
|
||||
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.Control != nil {
|
||||
if b.NumControls() != 0 {
|
||||
f.Fatalf("plain/dead block %s has a control value", b)
|
||||
}
|
||||
}
|
||||
|
|
@ -263,8 +263,10 @@ func checkFunc(f *Func) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if b.Control != nil && !valueMark[b.Control.ID] {
|
||||
f.Fatalf("control value for %s is missing: %v", b, b.Control)
|
||||
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 {
|
||||
|
|
@ -296,8 +298,10 @@ func checkFunc(f *Func) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if b.Control != nil && !domCheck(f, sdom, b.Control.Block, b) {
|
||||
f.Fatalf("control value %s for %s doesn't dominate", b.Control, b)
|
||||
for _, c := range b.ControlValues() {
|
||||
if !domCheck(f, sdom, c.Block, b) {
|
||||
f.Fatalf("control value %s for %s doesn't dominate", c, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -329,8 +333,8 @@ func checkFunc(f *Func) {
|
|||
uses[a.ID]++
|
||||
}
|
||||
}
|
||||
if b.Control != nil {
|
||||
uses[b.Control.ID]++
|
||||
for _, c := range b.ControlValues() {
|
||||
uses[c.ID]++
|
||||
}
|
||||
}
|
||||
for _, b := range f.Blocks {
|
||||
|
|
|
|||
|
|
@ -17,8 +17,10 @@ func copyelim(f *Func) {
|
|||
|
||||
// Update block control values.
|
||||
for _, b := range f.Blocks {
|
||||
if v := b.Control; v != nil && v.Op == OpCopy {
|
||||
b.SetControl(v.Args[0])
|
||||
for i, v := range b.ControlValues() {
|
||||
if v.Op == OpCopy {
|
||||
b.ReplaceControl(i, v.Args[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -248,14 +248,14 @@ func cse(f *Func) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if v := b.Control; v != nil {
|
||||
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.SetControl(x)
|
||||
b.ReplaceControl(i, x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,13 +110,15 @@ func liveValues(f *Func, reachable []bool) (live []bool, liveOrderStmts []*Value
|
|||
if !reachable[b.ID] {
|
||||
continue
|
||||
}
|
||||
if v := b.Control; v != nil && !live[v.ID] {
|
||||
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
|
||||
|
|
@ -252,7 +254,7 @@ func deadcode(f *Func) {
|
|||
for i, b := range f.Blocks {
|
||||
if !reachable[b.ID] {
|
||||
// TODO what if control is statement boundary? Too late here.
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
}
|
||||
for _, v := range b.Values {
|
||||
if !live[v.ID] {
|
||||
|
|
|
|||
|
|
@ -264,14 +264,13 @@ func elimDeadAutosGeneric(f *Func) {
|
|||
changed = visit(v) || changed
|
||||
}
|
||||
// keep the auto if its address reaches a control value
|
||||
if b.Control == nil {
|
||||
continue
|
||||
}
|
||||
if n, ok := addr[b.Control]; ok && !used[n] {
|
||||
for _, c := range b.ControlValues() {
|
||||
if n, ok := addr[c]; ok && !used[n] {
|
||||
used[n] = true
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if !changed {
|
||||
break
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,17 @@ func flagalloc(f *Func) {
|
|||
// Walk values backwards to figure out what flag
|
||||
// value we want in the flag register at the start
|
||||
// of the block.
|
||||
flag := end[b.ID]
|
||||
if b.Control != nil && b.Control.Type.IsFlags() {
|
||||
flag = b.Control
|
||||
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]
|
||||
|
|
@ -49,13 +57,15 @@ func flagalloc(f *Func) {
|
|||
// 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 {
|
||||
v := b.Control
|
||||
if v != nil && v.Type.IsFlags() && end[b.ID] != v {
|
||||
end[b.ID] = nil
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,9 +95,11 @@ func flagalloc(f *Func) {
|
|||
flag = v
|
||||
}
|
||||
}
|
||||
if v := b.Control; v != nil && v != flag && v.Type.IsFlags() {
|
||||
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
|
||||
}
|
||||
|
|
@ -149,12 +161,14 @@ func flagalloc(f *Func) {
|
|||
flag = v
|
||||
}
|
||||
}
|
||||
if v := b.Control; v != nil && v != flag && v.Type.IsFlags() {
|
||||
for i, v := range b.ControlValues() {
|
||||
if v != flag && v.Type.IsFlags() {
|
||||
// Recalculate control value.
|
||||
c := copyFlags(v, b)
|
||||
b.SetControl(c)
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ func fuseBlockIf(b *Block) bool {
|
|||
}
|
||||
b.Kind = BlockPlain
|
||||
b.Likely = BranchUnknown
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
|
||||
// Trash the empty blocks s0 and s1.
|
||||
blocks := [...]*Block{s0, s1}
|
||||
|
|
|
|||
|
|
@ -899,65 +899,65 @@
|
|||
(SBBLcarrymask (FlagGT_UGT)) -> (MOVLconst [0])
|
||||
|
||||
// Absorb flag constants into branches.
|
||||
(EQ (FlagEQ) yes no) -> (First nil yes no)
|
||||
(EQ (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil no yes)
|
||||
(NE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(NE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(NE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(NE (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil no yes)
|
||||
(LT (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(LT (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(LT (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(LT (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil yes no)
|
||||
(LE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(LE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(LE (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(LE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(GT (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(GT (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(GT (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(GT (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil yes no)
|
||||
(GE (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(GE (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(GE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(GE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(ULT (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(ULT (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(ULT (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(ULT (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil yes no)
|
||||
(ULE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(ULE (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(ULE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(ULE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(UGT (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(UGT (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(UGT (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(UGT (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil yes no)
|
||||
(UGE (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(UGE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(UGE (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(UGE (FlagGT_UGT) yes no) -> (First nil 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])
|
||||
|
|
|
|||
|
|
@ -564,22 +564,22 @@ func init() {
|
|||
}
|
||||
|
||||
var _386blocks = []blockData{
|
||||
{name: "EQ"},
|
||||
{name: "NE"},
|
||||
{name: "LT"},
|
||||
{name: "LE"},
|
||||
{name: "GT"},
|
||||
{name: "GE"},
|
||||
{name: "OS"},
|
||||
{name: "OC"},
|
||||
{name: "ULT"},
|
||||
{name: "ULE"},
|
||||
{name: "UGT"},
|
||||
{name: "UGE"},
|
||||
{name: "EQF"},
|
||||
{name: "NEF"},
|
||||
{name: "ORD"}, // FP, ordered comparison (parity zero)
|
||||
{name: "NAN"}, // FP, unordered comparison (parity one)
|
||||
{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{
|
||||
|
|
|
|||
|
|
@ -1346,16 +1346,16 @@
|
|||
(SBBLcarrymask (FlagGT_UGT)) -> (MOVLconst [0])
|
||||
|
||||
// Absorb flag constants into branches.
|
||||
((EQ|LE|GE|ULE|UGE) (FlagEQ) yes no) -> (First nil yes no)
|
||||
((NE|LT|GT|ULT|UGT) (FlagEQ) yes no) -> (First nil no yes)
|
||||
((NE|LT|LE|ULT|ULE) (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
((EQ|GT|GE|UGT|UGE) (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
((NE|LT|LE|UGT|UGE) (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
((EQ|GT|GE|ULT|ULE) (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
((NE|GT|GE|ULT|ULE) (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
((EQ|LT|LE|UGT|UGE) (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
((NE|GT|GE|UGT|UGE) (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
((EQ|LT|LE|ULT|ULE) (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
((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])
|
||||
|
|
|
|||
|
|
@ -788,22 +788,22 @@ func init() {
|
|||
}
|
||||
|
||||
var AMD64blocks = []blockData{
|
||||
{name: "EQ"},
|
||||
{name: "NE"},
|
||||
{name: "LT"},
|
||||
{name: "LE"},
|
||||
{name: "GT"},
|
||||
{name: "GE"},
|
||||
{name: "OS"},
|
||||
{name: "OC"},
|
||||
{name: "ULT"},
|
||||
{name: "ULE"},
|
||||
{name: "UGT"},
|
||||
{name: "UGE"},
|
||||
{name: "EQF"},
|
||||
{name: "NEF"},
|
||||
{name: "ORD"}, // FP, ordered comparison (parity zero)
|
||||
{name: "NAN"}, // FP, unordered comparison (parity one)
|
||||
{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{
|
||||
|
|
|
|||
|
|
@ -647,65 +647,65 @@
|
|||
(CMPconst (SRLconst _ [c]) [n]) && 0 <= n && 0 < c && c <= 32 && (1<<uint32(32-c)) <= uint32(n) -> (FlagLT_ULT)
|
||||
|
||||
// absorb flag constants into branches
|
||||
(EQ (FlagEQ) yes no) -> (First nil yes no)
|
||||
(EQ (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil no yes)
|
||||
(NE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(NE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(NE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(NE (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil no yes)
|
||||
(LT (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(LT (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(LT (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(LT (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil yes no)
|
||||
(LE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(LE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(LE (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(LE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(GT (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(GT (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(GT (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(GT (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil yes no)
|
||||
(GE (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(GE (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(GE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(GE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(ULT (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(ULT (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(ULT (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(ULT (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil yes no)
|
||||
(ULE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(ULE (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(ULE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(ULE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(UGT (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(UGT (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(UGT (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(UGT (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil yes no)
|
||||
(UGE (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(UGE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(UGE (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(UGE (FlagGT_UGT) yes no) -> (First nil 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 InvertFlags into branches
|
||||
(LT (InvertFlags cmp) yes no) -> (GT cmp yes no)
|
||||
|
|
|
|||
|
|
@ -1481,74 +1481,74 @@
|
|||
(CMPWconst (MOVHUreg _) [c]) && 0xffff < int32(c) -> (FlagLT_ULT)
|
||||
|
||||
// absorb flag constants into branches
|
||||
(EQ (FlagEQ) yes no) -> (First nil yes no)
|
||||
(EQ (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil no yes)
|
||||
(NE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(NE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(NE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(NE (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil no yes)
|
||||
(LT (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(LT (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(LT (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(LT (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil yes no)
|
||||
(LE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(LE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(LE (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(LE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(GT (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(GT (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(GT (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(GT (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil yes no)
|
||||
(GE (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(GE (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(GE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(GE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(ULT (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(ULT (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(ULT (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(ULT (FlagGT_UGT) yes no) -> (First nil no yes)
|
||||
(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 nil yes no)
|
||||
(ULE (FlagLT_ULT) yes no) -> (First nil yes no)
|
||||
(ULE (FlagLT_UGT) yes no) -> (First nil no yes)
|
||||
(ULE (FlagGT_ULT) yes no) -> (First nil yes no)
|
||||
(ULE (FlagGT_UGT) yes no) -> (First nil 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 nil no yes)
|
||||
(UGT (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(UGT (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(UGT (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(UGT (FlagGT_UGT) yes no) -> (First nil yes no)
|
||||
(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 nil yes no)
|
||||
(UGE (FlagLT_ULT) yes no) -> (First nil no yes)
|
||||
(UGE (FlagLT_UGT) yes no) -> (First nil yes no)
|
||||
(UGE (FlagGT_ULT) yes no) -> (First nil no yes)
|
||||
(UGE (FlagGT_UGT) yes no) -> (First nil 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)
|
||||
|
||||
(Z (MOVDconst [0]) yes no) -> (First nil yes no)
|
||||
(Z (MOVDconst [c]) yes no) && c != 0 -> (First nil no yes)
|
||||
(NZ (MOVDconst [0]) yes no) -> (First nil no yes)
|
||||
(NZ (MOVDconst [c]) yes no) && c != 0 -> (First nil yes no)
|
||||
(ZW (MOVDconst [c]) yes no) && int32(c) == 0 -> (First nil yes no)
|
||||
(ZW (MOVDconst [c]) yes no) && int32(c) != 0 -> (First nil no yes)
|
||||
(NZW (MOVDconst [c]) yes no) && int32(c) == 0 -> (First nil no yes)
|
||||
(NZW (MOVDconst [c]) yes no) && int32(c) != 0 -> (First nil yes no)
|
||||
(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)
|
||||
|
|
|
|||
|
|
@ -678,26 +678,26 @@ func init() {
|
|||
}
|
||||
|
||||
blocks := []blockData{
|
||||
{name: "EQ"},
|
||||
{name: "NE"},
|
||||
{name: "LT"},
|
||||
{name: "LE"},
|
||||
{name: "GT"},
|
||||
{name: "GE"},
|
||||
{name: "ULT"},
|
||||
{name: "ULE"},
|
||||
{name: "UGT"},
|
||||
{name: "UGE"},
|
||||
{name: "Z"}, // Control == 0 (take a register instead of flags)
|
||||
{name: "NZ"}, // Control != 0
|
||||
{name: "ZW"}, // Control == 0, 32-bit
|
||||
{name: "NZW"}, // Control != 0, 32-bit
|
||||
{name: "TBZ"}, // Control & (1 << Aux.(int64)) == 0
|
||||
{name: "TBNZ"}, // Control & (1 << Aux.(int64)) != 0
|
||||
{name: "FLT"},
|
||||
{name: "FLE"},
|
||||
{name: "FGT"},
|
||||
{name: "FGE"},
|
||||
{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}, // Control & (1 << Aux.(int64)) == 0
|
||||
{name: "TBNZ", controls: 1}, // Control & (1 << Aux.(int64)) != 0
|
||||
{name: "FLT", controls: 1},
|
||||
{name: "FLE", controls: 1},
|
||||
{name: "FGT", controls: 1},
|
||||
{name: "FGE", controls: 1},
|
||||
}
|
||||
|
||||
archs = append(archs, arch{
|
||||
|
|
|
|||
|
|
@ -568,16 +568,16 @@ func init() {
|
|||
}
|
||||
|
||||
blocks := []blockData{
|
||||
{name: "EQ"},
|
||||
{name: "NE"},
|
||||
{name: "LT"},
|
||||
{name: "LE"},
|
||||
{name: "GT"},
|
||||
{name: "GE"},
|
||||
{name: "ULT"},
|
||||
{name: "ULE"},
|
||||
{name: "UGT"},
|
||||
{name: "UGE"},
|
||||
{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},
|
||||
}
|
||||
|
||||
archs = append(archs, arch{
|
||||
|
|
|
|||
|
|
@ -687,18 +687,18 @@
|
|||
(SGTUconst [c] (SRLconst _ [d])) && uint32(d) <= 31 && 0xffffffff>>uint32(d) < uint32(c) -> (MOVWconst [1])
|
||||
|
||||
// absorb constants into branches
|
||||
(EQ (MOVWconst [0]) yes no) -> (First nil yes no)
|
||||
(EQ (MOVWconst [c]) yes no) && c != 0 -> (First nil no yes)
|
||||
(NE (MOVWconst [0]) yes no) -> (First nil no yes)
|
||||
(NE (MOVWconst [c]) yes no) && c != 0 -> (First nil yes no)
|
||||
(LTZ (MOVWconst [c]) yes no) && int32(c) < 0 -> (First nil yes no)
|
||||
(LTZ (MOVWconst [c]) yes no) && int32(c) >= 0 -> (First nil no yes)
|
||||
(LEZ (MOVWconst [c]) yes no) && int32(c) <= 0 -> (First nil yes no)
|
||||
(LEZ (MOVWconst [c]) yes no) && int32(c) > 0 -> (First nil no yes)
|
||||
(GTZ (MOVWconst [c]) yes no) && int32(c) > 0 -> (First nil yes no)
|
||||
(GTZ (MOVWconst [c]) yes no) && int32(c) <= 0 -> (First nil no yes)
|
||||
(GEZ (MOVWconst [c]) yes no) && int32(c) >= 0 -> (First nil yes no)
|
||||
(GEZ (MOVWconst [c]) yes no) && int32(c) < 0 -> (First nil no yes)
|
||||
(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) && int32(c) < 0 -> (First yes no)
|
||||
(LTZ (MOVWconst [c]) yes no) && int32(c) >= 0 -> (First no yes)
|
||||
(LEZ (MOVWconst [c]) yes no) && int32(c) <= 0 -> (First yes no)
|
||||
(LEZ (MOVWconst [c]) yes no) && int32(c) > 0 -> (First no yes)
|
||||
(GTZ (MOVWconst [c]) yes no) && int32(c) > 0 -> (First yes no)
|
||||
(GTZ (MOVWconst [c]) yes no) && int32(c) <= 0 -> (First no yes)
|
||||
(GEZ (MOVWconst [c]) yes no) && int32(c) >= 0 -> (First yes no)
|
||||
(GEZ (MOVWconst [c]) yes no) && int32(c) < 0 -> (First no yes)
|
||||
|
||||
// conditional move
|
||||
(CMOVZ _ f (MOVWconst [0])) -> f
|
||||
|
|
|
|||
|
|
@ -694,15 +694,15 @@
|
|||
(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 nil yes no)
|
||||
(EQ (MOVVconst [c]) yes no) && c != 0 -> (First nil no yes)
|
||||
(NE (MOVVconst [0]) yes no) -> (First nil no yes)
|
||||
(NE (MOVVconst [c]) yes no) && c != 0 -> (First nil yes no)
|
||||
(LTZ (MOVVconst [c]) yes no) && c < 0 -> (First nil yes no)
|
||||
(LTZ (MOVVconst [c]) yes no) && c >= 0 -> (First nil no yes)
|
||||
(LEZ (MOVVconst [c]) yes no) && c <= 0 -> (First nil yes no)
|
||||
(LEZ (MOVVconst [c]) yes no) && c > 0 -> (First nil no yes)
|
||||
(GTZ (MOVVconst [c]) yes no) && c > 0 -> (First nil yes no)
|
||||
(GTZ (MOVVconst [c]) yes no) && c <= 0 -> (First nil no yes)
|
||||
(GEZ (MOVVconst [c]) yes no) && c >= 0 -> (First nil yes no)
|
||||
(GEZ (MOVVconst [c]) yes no) && c < 0 -> (First nil no yes)
|
||||
(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)
|
||||
|
|
|
|||
|
|
@ -453,14 +453,14 @@ func init() {
|
|||
}
|
||||
|
||||
blocks := []blockData{
|
||||
{name: "EQ"},
|
||||
{name: "NE"},
|
||||
{name: "LTZ"}, // < 0
|
||||
{name: "LEZ"}, // <= 0
|
||||
{name: "GTZ"}, // > 0
|
||||
{name: "GEZ"}, // >= 0
|
||||
{name: "FPT"}, // FP flag is true
|
||||
{name: "FPF"}, // FP flag is false
|
||||
{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{
|
||||
|
|
|
|||
|
|
@ -409,14 +409,14 @@ func init() {
|
|||
}
|
||||
|
||||
blocks := []blockData{
|
||||
{name: "EQ"},
|
||||
{name: "NE"},
|
||||
{name: "LTZ"}, // < 0
|
||||
{name: "LEZ"}, // <= 0
|
||||
{name: "GTZ"}, // > 0
|
||||
{name: "GEZ"}, // >= 0
|
||||
{name: "FPT"}, // FP flag is true
|
||||
{name: "FPF"}, // FP flag is false
|
||||
{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{
|
||||
|
|
|
|||
|
|
@ -447,29 +447,29 @@
|
|||
(NE (CMPWconst [0] (ANDconst [c] x)) yes no) -> (NE (ANDCCconst [c] x) yes no)
|
||||
|
||||
// absorb flag constants into branches
|
||||
(EQ (FlagEQ) yes no) -> (First nil yes no)
|
||||
(EQ (FlagLT) yes no) -> (First nil no yes)
|
||||
(EQ (FlagGT) yes no) -> (First nil no yes)
|
||||
(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 nil no yes)
|
||||
(NE (FlagLT) yes no) -> (First nil yes no)
|
||||
(NE (FlagGT) yes no) -> (First nil yes no)
|
||||
(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 nil no yes)
|
||||
(LT (FlagLT) yes no) -> (First nil yes no)
|
||||
(LT (FlagGT) yes no) -> (First nil no yes)
|
||||
(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 nil yes no)
|
||||
(LE (FlagLT) yes no) -> (First nil yes no)
|
||||
(LE (FlagGT) yes no) -> (First nil 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 nil no yes)
|
||||
(GT (FlagLT) yes no) -> (First nil no yes)
|
||||
(GT (FlagGT) yes no) -> (First nil yes no)
|
||||
(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 nil yes no)
|
||||
(GE (FlagLT) yes no) -> (First nil no yes)
|
||||
(GE (FlagGT) yes no) -> (First nil 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)
|
||||
|
|
|
|||
|
|
@ -585,16 +585,16 @@ func init() {
|
|||
}
|
||||
|
||||
blocks := []blockData{
|
||||
{name: "EQ"},
|
||||
{name: "NE"},
|
||||
{name: "LT"},
|
||||
{name: "LE"},
|
||||
{name: "GT"},
|
||||
{name: "GE"},
|
||||
{name: "FLT"},
|
||||
{name: "FLE"},
|
||||
{name: "FGT"},
|
||||
{name: "FGE"},
|
||||
{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{
|
||||
|
|
|
|||
|
|
@ -976,15 +976,15 @@
|
|||
(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.CCMask) & s390x.Equal != 0 -> (First nil yes no)
|
||||
(BRC {c} (FlagLT) yes no) && c.(s390x.CCMask) & s390x.Less != 0 -> (First nil yes no)
|
||||
(BRC {c} (FlagGT) yes no) && c.(s390x.CCMask) & s390x.Greater != 0 -> (First nil yes no)
|
||||
(BRC {c} (FlagOV) yes no) && c.(s390x.CCMask) & s390x.Unordered != 0 -> (First nil yes no)
|
||||
(BRC {c} (FlagEQ) yes no) && c.(s390x.CCMask) & s390x.Equal != 0 -> (First yes no)
|
||||
(BRC {c} (FlagLT) yes no) && c.(s390x.CCMask) & s390x.Less != 0 -> (First yes no)
|
||||
(BRC {c} (FlagGT) yes no) && c.(s390x.CCMask) & s390x.Greater != 0 -> (First yes no)
|
||||
(BRC {c} (FlagOV) yes no) && c.(s390x.CCMask) & s390x.Unordered != 0 -> (First yes no)
|
||||
|
||||
(BRC {c} (FlagEQ) yes no) && c.(s390x.CCMask) & s390x.Equal == 0 -> (First nil no yes)
|
||||
(BRC {c} (FlagLT) yes no) && c.(s390x.CCMask) & s390x.Less == 0 -> (First nil no yes)
|
||||
(BRC {c} (FlagGT) yes no) && c.(s390x.CCMask) & s390x.Greater == 0 -> (First nil no yes)
|
||||
(BRC {c} (FlagOV) yes no) && c.(s390x.CCMask) & s390x.Unordered == 0 -> (First nil no yes)
|
||||
(BRC {c} (FlagEQ) yes no) && c.(s390x.CCMask) & s390x.Equal == 0 -> (First no yes)
|
||||
(BRC {c} (FlagLT) yes no) && c.(s390x.CCMask) & s390x.Less == 0 -> (First no yes)
|
||||
(BRC {c} (FlagGT) yes no) && c.(s390x.CCMask) & s390x.Greater == 0 -> (First no yes)
|
||||
(BRC {c} (FlagOV) yes no) && c.(s390x.CCMask) & s390x.Unordered == 0 -> (First no yes)
|
||||
|
||||
// Absorb flag constants into SETxx ops.
|
||||
(LOCGR {c} _ x (FlagEQ)) && c.(s390x.CCMask) & s390x.Equal != 0 -> x
|
||||
|
|
|
|||
|
|
@ -708,7 +708,7 @@ func init() {
|
|||
}
|
||||
|
||||
var S390Xblocks = []blockData{
|
||||
{name: "BRC"}, // aux is condition code mask (s390x.CCMask)
|
||||
{name: "BRC", controls: 1}, // aux is condition code mask (s390x.CCMask)
|
||||
}
|
||||
|
||||
archs = append(archs, arch{
|
||||
|
|
|
|||
|
|
@ -879,8 +879,8 @@
|
|||
(NilCheck (GetG mem) mem) -> mem
|
||||
|
||||
(If (Not cond) yes no) -> (If cond no yes)
|
||||
(If (ConstBool [c]) yes no) && c == 1 -> (First nil yes no)
|
||||
(If (ConstBool [c]) yes no) && c == 0 -> (First nil no yes)
|
||||
(If (ConstBool [c]) yes no) && c == 1 -> (First yes no)
|
||||
(If (ConstBool [c]) yes no) && c == 0 -> (First no yes)
|
||||
|
||||
// Get rid of Convert ops for pointer arithmetic on unsafe.Pointer.
|
||||
(Convert (Add(64|32) (Convert ptr mem) off) mem) -> (Add(64|32) ptr off)
|
||||
|
|
|
|||
|
|
@ -557,24 +557,22 @@ var genericOps = []opData{
|
|||
{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 control successors implicit exit
|
||||
// kind controls successors implicit exit
|
||||
// ----------------------------------------------------------
|
||||
// Exit return mem [] yes
|
||||
// Ret return mem [] yes
|
||||
// RetJmp return mem [] yes
|
||||
// Plain nil [next]
|
||||
// If a boolean Value [then, else]
|
||||
// Call mem [next] yes (control opcode should be OpCall or OpStaticCall)
|
||||
// Check void [next] yes (control opcode should be Op{Lowered}NilCheck)
|
||||
// First nil [always,never]
|
||||
// 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"}, // 2 successors, if control goto Succs[0] else goto Succs[1]
|
||||
{name: "Defer"}, // 2 successors, Succs[0]=defer queued, Succs[1]=defer recovered. control is call op (of memory type)
|
||||
{name: "Ret"}, // no successors, control value is memory result
|
||||
{name: "RetJmp"}, // no successors, jumps to b.Aux.(*gc.Sym)
|
||||
{name: "Exit"}, // no successors, control value generates a panic
|
||||
{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)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ type opData struct {
|
|||
}
|
||||
|
||||
type blockData struct {
|
||||
name string
|
||||
name string // the suffix for this block ("EQ", "LT", etc.)
|
||||
controls int // the number of control values this type of block requires
|
||||
}
|
||||
|
||||
type regInfo struct {
|
||||
|
|
|
|||
|
|
@ -238,7 +238,6 @@ func genRulesSuffix(arch arch, suff string) {
|
|||
fn = &Func{kind: "Block"}
|
||||
fn.add(declf("config", "b.Func.Config"))
|
||||
fn.add(declf("typ", "&b.Func.Config.Types"))
|
||||
fn.add(declf("v", "b.Control"))
|
||||
|
||||
sw = &Switch{expr: exprf("b.Kind")}
|
||||
ops = ops[:0]
|
||||
|
|
@ -247,9 +246,10 @@ func genRulesSuffix(arch arch, suff string) {
|
|||
}
|
||||
sort.Strings(ops)
|
||||
for _, op := range ops {
|
||||
swc := &Case{expr: exprf("%s", blockName(op, arch))}
|
||||
name, data := getBlockInfo(op, arch)
|
||||
swc := &Case{expr: exprf("%s", name)}
|
||||
for _, rule := range blockrules[op] {
|
||||
swc.add(genBlockRewrite(rule, arch))
|
||||
swc.add(genBlockRewrite(rule, arch, data))
|
||||
}
|
||||
sw.add(swc)
|
||||
}
|
||||
|
|
@ -593,11 +593,7 @@ func fprint(w io.Writer, n Node) {
|
|||
fmt.Fprintf(w, "// cond: %s\n", n.cond)
|
||||
}
|
||||
fmt.Fprintf(w, "// result: %s\n", n.result)
|
||||
if n.checkOp != "" {
|
||||
fmt.Fprintf(w, "for v.Op == %s {\n", n.checkOp)
|
||||
} else {
|
||||
fmt.Fprintf(w, "for {\n")
|
||||
}
|
||||
fmt.Fprintf(w, "for %s {\n", n.check)
|
||||
for _, n := range n.list {
|
||||
fprint(w, n)
|
||||
}
|
||||
|
|
@ -700,7 +696,7 @@ type (
|
|||
RuleRewrite struct {
|
||||
bodyBase
|
||||
match, cond, result string // top comments
|
||||
checkOp string
|
||||
check string // top-level boolean expression
|
||||
|
||||
alloc int // for unique var names
|
||||
loc string // file name & line number of the original rule
|
||||
|
|
@ -750,18 +746,39 @@ func breakf(format string, a ...interface{}) *CondBreak {
|
|||
return &CondBreak{exprf(format, a...)}
|
||||
}
|
||||
|
||||
func genBlockRewrite(rule Rule, arch arch) *RuleRewrite {
|
||||
func genBlockRewrite(rule Rule, arch arch, data blockData) *RuleRewrite {
|
||||
rr := &RuleRewrite{loc: rule.loc}
|
||||
rr.match, rr.cond, rr.result = rule.parse()
|
||||
_, _, _, aux, s := extract(rr.match) // remove parens, then split
|
||||
|
||||
// check match of control value
|
||||
pos := ""
|
||||
if s[0] != "nil" {
|
||||
if strings.Contains(s[0], "(") {
|
||||
pos, rr.checkOp = genMatch0(rr, arch, s[0], "v")
|
||||
// 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 {
|
||||
if strings.Contains(arg, "(") {
|
||||
// TODO: allow custom names?
|
||||
cname := fmt.Sprintf("b.Controls[%v]", i)
|
||||
vname := fmt.Sprintf("v_%v", i)
|
||||
rr.add(declf(vname, cname))
|
||||
p, op := genMatch0(rr, arch, arg, vname)
|
||||
if op != "" {
|
||||
check := fmt.Sprintf("%s.Op == %s", cname, op)
|
||||
if rr.check == "" {
|
||||
rr.check = check
|
||||
} else {
|
||||
rr.add(declf(s[0], "b.Control"))
|
||||
rr.check = rr.check + " && " + check
|
||||
}
|
||||
}
|
||||
if p == "" {
|
||||
p = vname + ".Pos"
|
||||
}
|
||||
pos[i] = p
|
||||
} else {
|
||||
rr.add(declf(arg, "b.Controls[%v]", i))
|
||||
pos[i] = arg + ".Pos"
|
||||
}
|
||||
}
|
||||
if aux != "" {
|
||||
|
|
@ -773,10 +790,14 @@ func genBlockRewrite(rule Rule, arch arch) *RuleRewrite {
|
|||
|
||||
// Rule matches. Generate result.
|
||||
outop, _, _, aux, t := extract(rr.result) // remove parens, then split
|
||||
newsuccs := t[1:]
|
||||
_, 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[1:]
|
||||
succs := s[data.controls:]
|
||||
newsuccs := t[outdata.controls:]
|
||||
m := map[string]bool{}
|
||||
for _, succ := range succs {
|
||||
if m[succ] {
|
||||
|
|
@ -794,15 +815,23 @@ func genBlockRewrite(rule Rule, arch arch) *RuleRewrite {
|
|||
log.Fatalf("unmatched successors %v in %s", m, rule)
|
||||
}
|
||||
|
||||
rr.add(stmtf("b.Kind = %s", blockName(outop, arch)))
|
||||
if t[0] == "nil" {
|
||||
rr.add(stmtf("b.SetControl(nil)"))
|
||||
} else {
|
||||
if pos == "" {
|
||||
pos = "v.Pos"
|
||||
blockName, _ := getBlockInfo(outop, arch)
|
||||
rr.add(stmtf("b.Kind = %s", blockName))
|
||||
rr.add(stmtf("b.ResetControls()"))
|
||||
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]
|
||||
}
|
||||
v := genResult0(rr, arch, t[0], false, false, pos)
|
||||
rr.add(stmtf("b.SetControl(%s)", v))
|
||||
|
||||
// Generate a new control value (or copy an existing value).
|
||||
v := genResult0(rr, arch, control, false, false, newpos)
|
||||
rr.add(stmtf("b.AddControl(%s)", v))
|
||||
}
|
||||
if aux != "" {
|
||||
rr.add(stmtf("b.Aux = %s", aux))
|
||||
|
|
@ -1164,13 +1193,19 @@ func parseValue(val string, arch arch, loc string) (op opData, oparch, typ, auxi
|
|||
return
|
||||
}
|
||||
|
||||
func blockName(name string, arch arch) string {
|
||||
func getBlockInfo(op string, arch arch) (name string, data blockData) {
|
||||
for _, b := range genericBlocks {
|
||||
if b.name == name {
|
||||
return "Block" + name
|
||||
if b.name == op {
|
||||
return "Block" + op, b
|
||||
}
|
||||
}
|
||||
return "Block" + arch.name + name
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -846,8 +846,8 @@ func (b *Block) LongHTML() string {
|
|||
if b.Aux != nil {
|
||||
s += html.EscapeString(fmt.Sprintf(" {%v}", b.Aux))
|
||||
}
|
||||
if b.Control != nil {
|
||||
s += fmt.Sprintf(" %s", b.Control.HTML())
|
||||
for _, c := range b.ControlValues() {
|
||||
s += fmt.Sprintf(" %s", c.HTML())
|
||||
}
|
||||
if len(b.Succs) > 0 {
|
||||
s += " →" // right arrow
|
||||
|
|
|
|||
|
|
@ -96,17 +96,18 @@ func findIndVar(f *Func) []indVar {
|
|||
// Check thet the control if it either ind </<= max or max >/>= ind.
|
||||
// TODO: Handle 32-bit comparisons.
|
||||
// TODO: Handle unsigned comparisons?
|
||||
switch b.Control.Op {
|
||||
c := b.Controls[0]
|
||||
switch c.Op {
|
||||
case OpLeq64:
|
||||
flags |= indVarMaxInc
|
||||
fallthrough
|
||||
case OpLess64:
|
||||
ind, max = b.Control.Args[0], b.Control.Args[1]
|
||||
ind, max = c.Args[0], c.Args[1]
|
||||
case OpGeq64:
|
||||
flags |= indVarMaxInc
|
||||
fallthrough
|
||||
case OpGreater64:
|
||||
ind, max = b.Control.Args[1], b.Control.Args[0]
|
||||
ind, max = c.Args[1], c.Args[0]
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
|
@ -207,7 +208,7 @@ func findIndVar(f *Func) []indVar {
|
|||
}
|
||||
// Handle induction variables of these forms.
|
||||
// KNN is known-not-negative.
|
||||
// SIGNED ARITHMETIC ONLY. (see switch on b.Control.Op above)
|
||||
// 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
|
||||
|
|
|
|||
|
|
@ -99,9 +99,8 @@ func nilcheckelim(f *Func) {
|
|||
// 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.Control.Op == OpIsNonNil && p.Succs[0].b == b {
|
||||
ptr := p.Control.Args[0]
|
||||
if !nonNilValues[ptr.ID] {
|
||||
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})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ 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.Control.Op == OpIsNonNil
|
||||
return b.Kind == BlockIf && b.Controls[0].Op == OpIsNonNil
|
||||
}
|
||||
|
||||
// TestNilcheckSimple verifies that a second repeated nilcheck is removed.
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ func phiopt(f *Func) {
|
|||
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.Control)
|
||||
v.AddArg(b0.Controls[0])
|
||||
if f.pass.debug > 0 {
|
||||
f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ func phiopt(f *Func) {
|
|||
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.Control, tmp)
|
||||
v.SetArgs2(b0.Controls[0], tmp)
|
||||
if f.pass.debug > 0 {
|
||||
f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
|
||||
}
|
||||
|
|
@ -111,7 +111,7 @@ func phiopt(f *Func) {
|
|||
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.Control, tmp)
|
||||
v.SetArgs2(b0.Controls[0], tmp)
|
||||
if f.pass.debug > 0 {
|
||||
f.Warnl(b.Pos, "converted OpPhi to %v", v.Op)
|
||||
}
|
||||
|
|
@ -161,7 +161,7 @@ func phioptint(v *Value, b0 *Block, reverse int) {
|
|||
v.Fatalf("bad int size %d", v.Type.Size())
|
||||
}
|
||||
|
||||
a := b0.Control
|
||||
a := b0.Controls[0]
|
||||
if negate {
|
||||
a = v.Block.NewValue1(v.Pos, OpNot, a.Type, a)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -979,7 +979,7 @@ func addIndVarRestrictions(ft *factsTable, b *Block, iv indVar) {
|
|||
// 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.Control
|
||||
c := b.Controls[0]
|
||||
switch br {
|
||||
case negative:
|
||||
addRestrictions(b, ft, boolean, nil, c, eq)
|
||||
|
|
@ -988,14 +988,14 @@ func addBranchRestrictions(ft *factsTable, b *Block, br branch) {
|
|||
default:
|
||||
panic("unknown branch")
|
||||
}
|
||||
if tr, has := domainRelationTable[b.Control.Op]; has {
|
||||
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 b.Control.Op {
|
||||
switch c.Op {
|
||||
case OpIsInBounds, OpIsSliceInBounds:
|
||||
// 0 <= a0 < a1 (or 0 <= a0 <= a1)
|
||||
//
|
||||
|
|
@ -1096,6 +1096,7 @@ func addLocalInductiveFacts(ft *factsTable, b *Block) {
|
|||
if pred.Kind != BlockIf {
|
||||
continue
|
||||
}
|
||||
control := pred.Controls[0]
|
||||
|
||||
br := unknown
|
||||
if pred.Succs[0].b == child {
|
||||
|
|
@ -1108,7 +1109,7 @@ func addLocalInductiveFacts(ft *factsTable, b *Block) {
|
|||
br = negative
|
||||
}
|
||||
|
||||
tr, has := domainRelationTable[pred.Control.Op]
|
||||
tr, has := domainRelationTable[control.Op]
|
||||
if !has {
|
||||
continue
|
||||
}
|
||||
|
|
@ -1121,10 +1122,10 @@ func addLocalInductiveFacts(ft *factsTable, b *Block) {
|
|||
|
||||
// Check for i2 < max or max > i2.
|
||||
var max *Value
|
||||
if r == lt && pred.Control.Args[0] == i2 {
|
||||
max = pred.Control.Args[1]
|
||||
} else if r == gt && pred.Control.Args[1] == i2 {
|
||||
max = pred.Control.Args[0]
|
||||
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
|
||||
}
|
||||
|
|
@ -1288,7 +1289,7 @@ func removeBranch(b *Block, branch branch) {
|
|||
if branch == positive {
|
||||
verb = "Disproved"
|
||||
}
|
||||
c := b.Control
|
||||
c := b.Controls[0]
|
||||
if b.Func.pass.debug > 1 {
|
||||
b.Func.Warnl(b.Pos, "%s %s (%s)", verb, c.Op, c)
|
||||
} else {
|
||||
|
|
@ -1296,7 +1297,7 @@ func removeBranch(b *Block, branch branch) {
|
|||
}
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
if branch == positive {
|
||||
b.swapSuccessors()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -701,8 +701,10 @@ func (s *regAllocState) init(f *Func) {
|
|||
for _, b := range f.Blocks {
|
||||
// New block. Clear candidate set.
|
||||
canLiveOnStack.clear()
|
||||
if b.Control != nil && b.Control.Uses == 1 && !opcodeTable[b.Control.Op].generic {
|
||||
canLiveOnStack.add(b.Control.ID)
|
||||
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-- {
|
||||
|
|
@ -856,10 +858,12 @@ func (s *regAllocState) regalloc(f *Func) {
|
|||
s.addUse(e.ID, int32(len(b.Values))+e.dist, e.pos) // pseudo-uses from beyond end of block
|
||||
regValLiveSet.add(e.ID)
|
||||
}
|
||||
if v := b.Control; v != nil && s.values[v.ID].needReg {
|
||||
s.addUse(v.ID, int32(len(b.Values)), b.Pos) // pseudo-use by control value
|
||||
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)
|
||||
|
|
@ -1503,21 +1507,32 @@ func (s *regAllocState) regalloc(f *Func) {
|
|||
issueSpill:
|
||||
}
|
||||
|
||||
// Load control value into reg.
|
||||
if v := b.Control; v != nil && s.values[v.ID].needReg {
|
||||
// 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.Control = s.allocValToReg(v, s.compatRegs(v.Type), false, b.Pos)
|
||||
if b.Control != v {
|
||||
v.Uses--
|
||||
b.Control.Uses++
|
||||
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.
|
||||
vi := &s.values[v.ID]
|
||||
u := vi.uses
|
||||
vi.uses = u.next
|
||||
if u.next == nil {
|
||||
|
|
@ -2355,9 +2370,11 @@ func (s *regAllocState) computeLive() {
|
|||
live.set(e.ID, e.dist+int32(len(b.Values)), e.pos)
|
||||
}
|
||||
|
||||
// Mark control value as live
|
||||
if b.Control != nil && s.values[b.Control.ID].needReg {
|
||||
live.set(b.Control.ID, int32(len(b.Values)), b.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
|
||||
|
|
|
|||
|
|
@ -25,9 +25,10 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter) {
|
|||
for {
|
||||
change := false
|
||||
for _, b := range f.Blocks {
|
||||
if b.Control != nil && b.Control.Op == OpCopy {
|
||||
for b.Control.Op == OpCopy {
|
||||
b.SetControl(b.Control.Args[0])
|
||||
for i, c := range b.ControlValues() {
|
||||
for c.Op == OpCopy {
|
||||
c = c.Args[0]
|
||||
b.ReplaceControl(i, c)
|
||||
}
|
||||
}
|
||||
if rb(b) {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -8995,182 +8995,207 @@ func rewriteValueMIPS_OpZeromask_0(v *Value) bool {
|
|||
}
|
||||
}
|
||||
func rewriteBlockMIPS(b *Block) bool {
|
||||
v := b.Control
|
||||
switch b.Kind {
|
||||
case BlockMIPSEQ:
|
||||
// match: (EQ (FPFlagTrue cmp) yes no)
|
||||
// result: (FPF cmp yes no)
|
||||
for v.Op == OpMIPSFPFlagTrue {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPSFPFlagTrue {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
b.Kind = BlockMIPSFPF
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (FPFlagFalse cmp) yes no)
|
||||
// result: (FPT cmp yes no)
|
||||
for v.Op == OpMIPSFPFlagFalse {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPSFPFlagFalse {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
b.Kind = BlockMIPSFPT
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGT _ _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGT {
|
||||
break
|
||||
}
|
||||
_ = cmp.Args[1]
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGTU _ _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTU {
|
||||
break
|
||||
}
|
||||
_ = cmp.Args[1]
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGTconst _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTconst {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGTUconst _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTUconst {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGTzero _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTzero {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGTUzero _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTUzero {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (SGTUconst [1] x) yes no)
|
||||
// result: (NE x yes no)
|
||||
for v.Op == OpMIPSSGTUconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSSGTUconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
x := v.Args[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (SGTUzero x) yes no)
|
||||
// result: (EQ x yes no)
|
||||
for v.Op == OpMIPSSGTUzero {
|
||||
x := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPSSGTUzero {
|
||||
v_0 := b.Controls[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPSEQ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (SGTconst [0] x) yes no)
|
||||
// result: (GEZ x yes no)
|
||||
for v.Op == OpMIPSSGTconst {
|
||||
if v.AuxInt != 0 {
|
||||
for b.Controls[0].Op == OpMIPSSGTconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
x := v.Args[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPSGEZ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (SGTzero x) yes no)
|
||||
// result: (LEZ x yes no)
|
||||
for v.Op == OpMIPSSGTzero {
|
||||
x := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPSSGTzero {
|
||||
v_0 := b.Controls[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPSLEZ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (MOVWconst [0]) yes no)
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
if v.AuxInt != 0 {
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (MOVWconst [c]) yes no)
|
||||
// cond: c != 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c != 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9178,27 +9203,29 @@ func rewriteBlockMIPS(b *Block) bool {
|
|||
case BlockMIPSGEZ:
|
||||
// match: (GEZ (MOVWconst [c]) yes no)
|
||||
// cond: int32(c) >= 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(int32(c) >= 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (GEZ (MOVWconst [c]) yes no)
|
||||
// cond: int32(c) < 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(int32(c) < 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9206,27 +9233,29 @@ func rewriteBlockMIPS(b *Block) bool {
|
|||
case BlockMIPSGTZ:
|
||||
// match: (GTZ (MOVWconst [c]) yes no)
|
||||
// cond: int32(c) > 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(int32(c) > 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (GTZ (MOVWconst [c]) yes no)
|
||||
// cond: int32(c) <= 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(int32(c) <= 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9235,36 +9264,39 @@ func rewriteBlockMIPS(b *Block) bool {
|
|||
// match: (If cond yes no)
|
||||
// result: (NE cond yes no)
|
||||
for {
|
||||
cond := b.Control
|
||||
cond := b.Controls[0]
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(cond)
|
||||
b.ResetControls()
|
||||
b.AddControl(cond)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
case BlockMIPSLEZ:
|
||||
// match: (LEZ (MOVWconst [c]) yes no)
|
||||
// cond: int32(c) <= 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(int32(c) <= 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (LEZ (MOVWconst [c]) yes no)
|
||||
// cond: int32(c) > 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(int32(c) > 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9272,27 +9304,29 @@ func rewriteBlockMIPS(b *Block) bool {
|
|||
case BlockMIPSLTZ:
|
||||
// match: (LTZ (MOVWconst [c]) yes no)
|
||||
// cond: int32(c) < 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(int32(c) < 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (LTZ (MOVWconst [c]) yes no)
|
||||
// cond: int32(c) >= 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(int32(c) >= 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9300,178 +9334,204 @@ func rewriteBlockMIPS(b *Block) bool {
|
|||
case BlockMIPSNE:
|
||||
// match: (NE (FPFlagTrue cmp) yes no)
|
||||
// result: (FPT cmp yes no)
|
||||
for v.Op == OpMIPSFPFlagTrue {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPSFPFlagTrue {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
b.Kind = BlockMIPSFPT
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (FPFlagFalse cmp) yes no)
|
||||
// result: (FPF cmp yes no)
|
||||
for v.Op == OpMIPSFPFlagFalse {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPSFPFlagFalse {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
b.Kind = BlockMIPSFPF
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGT _ _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGT {
|
||||
break
|
||||
}
|
||||
_ = cmp.Args[1]
|
||||
b.Kind = BlockMIPSEQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGTU _ _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTU {
|
||||
break
|
||||
}
|
||||
_ = cmp.Args[1]
|
||||
b.Kind = BlockMIPSEQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGTconst _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTconst {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPSEQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGTUconst _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTUconst {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPSEQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGTzero _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTzero {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPSEQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGTUzero _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPSXORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSXORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPSSGTUzero {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPSEQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (SGTUconst [1] x) yes no)
|
||||
// result: (EQ x yes no)
|
||||
for v.Op == OpMIPSSGTUconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPSSGTUconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
x := v.Args[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPSEQ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (SGTUzero x) yes no)
|
||||
// result: (NE x yes no)
|
||||
for v.Op == OpMIPSSGTUzero {
|
||||
x := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPSSGTUzero {
|
||||
v_0 := b.Controls[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPSNE
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (SGTconst [0] x) yes no)
|
||||
// result: (LTZ x yes no)
|
||||
for v.Op == OpMIPSSGTconst {
|
||||
if v.AuxInt != 0 {
|
||||
for b.Controls[0].Op == OpMIPSSGTconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
x := v.Args[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPSLTZ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (SGTzero x) yes no)
|
||||
// result: (GTZ x yes no)
|
||||
for v.Op == OpMIPSSGTzero {
|
||||
x := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPSSGTzero {
|
||||
v_0 := b.Controls[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPSGTZ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (MOVWconst [0]) yes no)
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
if v.AuxInt != 0 {
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
}
|
||||
// match: (NE (MOVWconst [c]) yes no)
|
||||
// cond: c != 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPSMOVWconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPSMOVWconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c != 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9740,162 +9740,183 @@ func rewriteValueMIPS64_OpZeroExt8to64_0(v *Value) bool {
|
|||
}
|
||||
}
|
||||
func rewriteBlockMIPS64(b *Block) bool {
|
||||
v := b.Control
|
||||
switch b.Kind {
|
||||
case BlockMIPS64EQ:
|
||||
// match: (EQ (FPFlagTrue cmp) yes no)
|
||||
// result: (FPF cmp yes no)
|
||||
for v.Op == OpMIPS64FPFlagTrue {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPS64FPFlagTrue {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
b.Kind = BlockMIPS64FPF
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (FPFlagFalse cmp) yes no)
|
||||
// result: (FPT cmp yes no)
|
||||
for v.Op == OpMIPS64FPFlagFalse {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPS64FPFlagFalse {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
b.Kind = BlockMIPS64FPT
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGT _ _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPS64XORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64XORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPS64SGT {
|
||||
break
|
||||
}
|
||||
_ = cmp.Args[1]
|
||||
b.Kind = BlockMIPS64NE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGTU _ _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPS64XORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64XORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPS64SGTU {
|
||||
break
|
||||
}
|
||||
_ = cmp.Args[1]
|
||||
b.Kind = BlockMIPS64NE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGTconst _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPS64XORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64XORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPS64SGTconst {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPS64NE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (XORconst [1] cmp:(SGTUconst _)) yes no)
|
||||
// result: (NE cmp yes no)
|
||||
for v.Op == OpMIPS64XORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64XORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPS64SGTUconst {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPS64NE
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (SGTUconst [1] x) yes no)
|
||||
// result: (NE x yes no)
|
||||
for v.Op == OpMIPS64SGTUconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64SGTUconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
x := v.Args[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPS64NE
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (SGTU x (MOVVconst [0])) yes no)
|
||||
// result: (EQ x yes no)
|
||||
for v.Op == OpMIPS64SGTU {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpMIPS64MOVVconst || v_1.AuxInt != 0 {
|
||||
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 || v_0_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPS64EQ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (SGTconst [0] x) yes no)
|
||||
// result: (GEZ x yes no)
|
||||
for v.Op == OpMIPS64SGTconst {
|
||||
if v.AuxInt != 0 {
|
||||
for b.Controls[0].Op == OpMIPS64SGTconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
x := v.Args[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPS64GEZ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (SGT x (MOVVconst [0])) yes no)
|
||||
// result: (LEZ x yes no)
|
||||
for v.Op == OpMIPS64SGT {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpMIPS64MOVVconst || v_1.AuxInt != 0 {
|
||||
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 || v_0_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPS64LEZ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (MOVVconst [0]) yes no)
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
if v.AuxInt != 0 {
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (EQ (MOVVconst [c]) yes no)
|
||||
// cond: c != 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c != 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9903,27 +9924,29 @@ func rewriteBlockMIPS64(b *Block) bool {
|
|||
case BlockMIPS64GEZ:
|
||||
// match: (GEZ (MOVVconst [c]) yes no)
|
||||
// cond: c >= 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c >= 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (GEZ (MOVVconst [c]) yes no)
|
||||
// cond: c < 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c < 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9931,27 +9954,29 @@ func rewriteBlockMIPS64(b *Block) bool {
|
|||
case BlockMIPS64GTZ:
|
||||
// match: (GTZ (MOVVconst [c]) yes no)
|
||||
// cond: c > 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c > 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (GTZ (MOVVconst [c]) yes no)
|
||||
// cond: c <= 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c <= 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9960,36 +9985,39 @@ func rewriteBlockMIPS64(b *Block) bool {
|
|||
// match: (If cond yes no)
|
||||
// result: (NE cond yes no)
|
||||
for {
|
||||
cond := b.Control
|
||||
cond := b.Controls[0]
|
||||
b.Kind = BlockMIPS64NE
|
||||
b.SetControl(cond)
|
||||
b.ResetControls()
|
||||
b.AddControl(cond)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
case BlockMIPS64LEZ:
|
||||
// match: (LEZ (MOVVconst [c]) yes no)
|
||||
// cond: c <= 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c <= 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (LEZ (MOVVconst [c]) yes no)
|
||||
// cond: c > 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c > 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -9997,27 +10025,29 @@ func rewriteBlockMIPS64(b *Block) bool {
|
|||
case BlockMIPS64LTZ:
|
||||
// match: (LTZ (MOVVconst [c]) yes no)
|
||||
// cond: c < 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c < 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (LTZ (MOVVconst [c]) yes no)
|
||||
// cond: c >= 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c >= 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -10025,158 +10055,180 @@ func rewriteBlockMIPS64(b *Block) bool {
|
|||
case BlockMIPS64NE:
|
||||
// match: (NE (FPFlagTrue cmp) yes no)
|
||||
// result: (FPT cmp yes no)
|
||||
for v.Op == OpMIPS64FPFlagTrue {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPS64FPFlagTrue {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
b.Kind = BlockMIPS64FPT
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (FPFlagFalse cmp) yes no)
|
||||
// result: (FPF cmp yes no)
|
||||
for v.Op == OpMIPS64FPFlagFalse {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpMIPS64FPFlagFalse {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
b.Kind = BlockMIPS64FPF
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGT _ _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPS64XORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64XORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPS64SGT {
|
||||
break
|
||||
}
|
||||
_ = cmp.Args[1]
|
||||
b.Kind = BlockMIPS64EQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGTU _ _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPS64XORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64XORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPS64SGTU {
|
||||
break
|
||||
}
|
||||
_ = cmp.Args[1]
|
||||
b.Kind = BlockMIPS64EQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGTconst _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPS64XORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64XORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPS64SGTconst {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPS64EQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (XORconst [1] cmp:(SGTUconst _)) yes no)
|
||||
// result: (EQ cmp yes no)
|
||||
for v.Op == OpMIPS64XORconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64XORconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
cmp := v.Args[0]
|
||||
cmp := v_0.Args[0]
|
||||
if cmp.Op != OpMIPS64SGTUconst {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPS64EQ
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (SGTUconst [1] x) yes no)
|
||||
// result: (EQ x yes no)
|
||||
for v.Op == OpMIPS64SGTUconst {
|
||||
if v.AuxInt != 1 {
|
||||
for b.Controls[0].Op == OpMIPS64SGTUconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 1 {
|
||||
break
|
||||
}
|
||||
x := v.Args[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPS64EQ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (SGTU x (MOVVconst [0])) yes no)
|
||||
// result: (NE x yes no)
|
||||
for v.Op == OpMIPS64SGTU {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpMIPS64MOVVconst || v_1.AuxInt != 0 {
|
||||
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 || v_0_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPS64NE
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (SGTconst [0] x) yes no)
|
||||
// result: (LTZ x yes no)
|
||||
for v.Op == OpMIPS64SGTconst {
|
||||
if v.AuxInt != 0 {
|
||||
for b.Controls[0].Op == OpMIPS64SGTconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
x := v.Args[0]
|
||||
x := v_0.Args[0]
|
||||
b.Kind = BlockMIPS64LTZ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (SGT x (MOVVconst [0])) yes no)
|
||||
// result: (GTZ x yes no)
|
||||
for v.Op == OpMIPS64SGT {
|
||||
_ = v.Args[1]
|
||||
x := v.Args[0]
|
||||
v_1 := v.Args[1]
|
||||
if v_1.Op != OpMIPS64MOVVconst || v_1.AuxInt != 0 {
|
||||
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 || v_0_1.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockMIPS64GTZ
|
||||
b.SetControl(x)
|
||||
b.ResetControls()
|
||||
b.AddControl(x)
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (NE (MOVVconst [0]) yes no)
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
if v.AuxInt != 0 {
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
}
|
||||
// match: (NE (MOVVconst [c]) yes no)
|
||||
// cond: c != 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpMIPS64MOVVconst {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpMIPS64MOVVconst {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c != 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -36449,37 +36449,38 @@ func rewriteValueS390X_OpZeroExt8to64_0(v *Value) bool {
|
|||
}
|
||||
func rewriteBlockS390X(b *Block) bool {
|
||||
typ := &b.Func.Config.Types
|
||||
v := b.Control
|
||||
switch b.Kind {
|
||||
case BlockS390XBRC:
|
||||
// match: (BRC {c} (CMPWconst [0] (LOCGR {d} (MOVDconst [0]) (MOVDconst [x]) cmp)) yes no)
|
||||
// cond: x != 0 && c.(s390x.CCMask) == s390x.Equal
|
||||
// result: (BRC {d} cmp no yes)
|
||||
for v.Op == OpS390XCMPWconst {
|
||||
if v.AuxInt != 0 {
|
||||
for b.Controls[0].Op == OpS390XCMPWconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XLOCGR {
|
||||
break
|
||||
}
|
||||
d := v_0.Aux
|
||||
cmp := v_0.Args[2]
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpS390XMOVDconst || v_0_0.AuxInt != 0 {
|
||||
if v_0_0.Op != OpS390XLOCGR {
|
||||
break
|
||||
}
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpS390XMOVDconst {
|
||||
d := v_0_0.Aux
|
||||
cmp := v_0_0.Args[2]
|
||||
v_0_0_0 := v_0_0.Args[0]
|
||||
if v_0_0_0.Op != OpS390XMOVDconst || v_0_0_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
x := v_0_1.AuxInt
|
||||
v_0_0_1 := v_0_0.Args[1]
|
||||
if v_0_0_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
x := v_0_0_1.AuxInt
|
||||
c := b.Aux
|
||||
if !(x != 0 && c.(s390x.CCMask) == s390x.Equal) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockS390XBRC
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = d
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -36487,148 +36488,152 @@ func rewriteBlockS390X(b *Block) bool {
|
|||
// match: (BRC {c} (CMPWconst [0] (LOCGR {d} (MOVDconst [0]) (MOVDconst [x]) cmp)) yes no)
|
||||
// cond: x != 0 && c.(s390x.CCMask) == s390x.NotEqual
|
||||
// result: (BRC {d} cmp yes no)
|
||||
for v.Op == OpS390XCMPWconst {
|
||||
if v.AuxInt != 0 {
|
||||
for b.Controls[0].Op == OpS390XCMPWconst {
|
||||
v_0 := b.Controls[0]
|
||||
if v_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
v_0 := v.Args[0]
|
||||
if v_0.Op != OpS390XLOCGR {
|
||||
break
|
||||
}
|
||||
d := v_0.Aux
|
||||
cmp := v_0.Args[2]
|
||||
v_0_0 := v_0.Args[0]
|
||||
if v_0_0.Op != OpS390XMOVDconst || v_0_0.AuxInt != 0 {
|
||||
if v_0_0.Op != OpS390XLOCGR {
|
||||
break
|
||||
}
|
||||
v_0_1 := v_0.Args[1]
|
||||
if v_0_1.Op != OpS390XMOVDconst {
|
||||
d := v_0_0.Aux
|
||||
cmp := v_0_0.Args[2]
|
||||
v_0_0_0 := v_0_0.Args[0]
|
||||
if v_0_0_0.Op != OpS390XMOVDconst || v_0_0_0.AuxInt != 0 {
|
||||
break
|
||||
}
|
||||
x := v_0_1.AuxInt
|
||||
v_0_0_1 := v_0_0.Args[1]
|
||||
if v_0_0_1.Op != OpS390XMOVDconst {
|
||||
break
|
||||
}
|
||||
x := v_0_0_1.AuxInt
|
||||
c := b.Aux
|
||||
if !(x != 0 && c.(s390x.CCMask) == s390x.NotEqual) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockS390XBRC
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = d
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (InvertFlags cmp) yes no)
|
||||
// result: (BRC {c.(s390x.CCMask).ReverseComparison()} cmp yes no)
|
||||
for v.Op == OpS390XInvertFlags {
|
||||
cmp := v.Args[0]
|
||||
for b.Controls[0].Op == OpS390XInvertFlags {
|
||||
v_0 := b.Controls[0]
|
||||
cmp := v_0.Args[0]
|
||||
c := b.Aux
|
||||
b.Kind = BlockS390XBRC
|
||||
b.SetControl(cmp)
|
||||
b.ResetControls()
|
||||
b.AddControl(cmp)
|
||||
b.Aux = c.(s390x.CCMask).ReverseComparison()
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (FlagEQ) yes no)
|
||||
// cond: c.(s390x.CCMask) & s390x.Equal != 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpS390XFlagEQ {
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpS390XFlagEQ {
|
||||
c := b.Aux
|
||||
if !(c.(s390x.CCMask)&s390x.Equal != 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (FlagLT) yes no)
|
||||
// cond: c.(s390x.CCMask) & s390x.Less != 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpS390XFlagLT {
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpS390XFlagLT {
|
||||
c := b.Aux
|
||||
if !(c.(s390x.CCMask)&s390x.Less != 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (FlagGT) yes no)
|
||||
// cond: c.(s390x.CCMask) & s390x.Greater != 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpS390XFlagGT {
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpS390XFlagGT {
|
||||
c := b.Aux
|
||||
if !(c.(s390x.CCMask)&s390x.Greater != 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (FlagOV) yes no)
|
||||
// cond: c.(s390x.CCMask) & s390x.Unordered != 0
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpS390XFlagOV {
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpS390XFlagOV {
|
||||
c := b.Aux
|
||||
if !(c.(s390x.CCMask)&s390x.Unordered != 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (FlagEQ) yes no)
|
||||
// cond: c.(s390x.CCMask) & s390x.Equal == 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpS390XFlagEQ {
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpS390XFlagEQ {
|
||||
c := b.Aux
|
||||
if !(c.(s390x.CCMask)&s390x.Equal == 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (FlagLT) yes no)
|
||||
// cond: c.(s390x.CCMask) & s390x.Less == 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpS390XFlagLT {
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpS390XFlagLT {
|
||||
c := b.Aux
|
||||
if !(c.(s390x.CCMask)&s390x.Less == 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (FlagGT) yes no)
|
||||
// cond: c.(s390x.CCMask) & s390x.Greater == 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpS390XFlagGT {
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpS390XFlagGT {
|
||||
c := b.Aux
|
||||
if !(c.(s390x.CCMask)&s390x.Greater == 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
}
|
||||
// match: (BRC {c} (FlagOV) yes no)
|
||||
// cond: c.(s390x.CCMask) & s390x.Unordered == 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpS390XFlagOV {
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpS390XFlagOV {
|
||||
c := b.Aux
|
||||
if !(c.(s390x.CCMask)&s390x.Unordered == 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
@ -36637,14 +36642,15 @@ func rewriteBlockS390X(b *Block) bool {
|
|||
// match: (If cond yes no)
|
||||
// result: (BRC {s390x.NotEqual} (CMPWconst [0] (MOVBZreg <typ.Bool> cond)) yes no)
|
||||
for {
|
||||
cond := b.Control
|
||||
cond := b.Controls[0]
|
||||
b.Kind = BlockS390XBRC
|
||||
v0 := b.NewValue0(v.Pos, OpS390XCMPWconst, types.TypeFlags)
|
||||
b.ResetControls()
|
||||
v0 := b.NewValue0(cond.Pos, OpS390XCMPWconst, types.TypeFlags)
|
||||
v0.AuxInt = 0
|
||||
v1 := b.NewValue0(v.Pos, OpS390XMOVBZreg, typ.Bool)
|
||||
v1 := b.NewValue0(cond.Pos, OpS390XMOVBZreg, typ.Bool)
|
||||
v1.AddArg(cond)
|
||||
v0.AddArg(v1)
|
||||
b.SetControl(v0)
|
||||
b.AddControl(v0)
|
||||
b.Aux = s390x.NotEqual
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47407,42 +47407,45 @@ func rewriteValuegeneric_OpZeroExt8to64_0(v *Value) bool {
|
|||
return false
|
||||
}
|
||||
func rewriteBlockgeneric(b *Block) bool {
|
||||
v := b.Control
|
||||
switch b.Kind {
|
||||
case BlockIf:
|
||||
// match: (If (Not cond) yes no)
|
||||
// result: (If cond no yes)
|
||||
for v.Op == OpNot {
|
||||
cond := v.Args[0]
|
||||
for b.Controls[0].Op == OpNot {
|
||||
v_0 := b.Controls[0]
|
||||
cond := v_0.Args[0]
|
||||
b.Kind = BlockIf
|
||||
b.SetControl(cond)
|
||||
b.ResetControls()
|
||||
b.AddControl(cond)
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
}
|
||||
// match: (If (ConstBool [c]) yes no)
|
||||
// cond: c == 1
|
||||
// result: (First nil yes no)
|
||||
for v.Op == OpConstBool {
|
||||
c := v.AuxInt
|
||||
// result: (First yes no)
|
||||
for b.Controls[0].Op == OpConstBool {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c == 1) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
return true
|
||||
}
|
||||
// match: (If (ConstBool [c]) yes no)
|
||||
// cond: c == 0
|
||||
// result: (First nil no yes)
|
||||
for v.Op == OpConstBool {
|
||||
c := v.AuxInt
|
||||
// result: (First no yes)
|
||||
for b.Controls[0].Op == OpConstBool {
|
||||
v_0 := b.Controls[0]
|
||||
c := v_0.AuxInt
|
||||
if !(c == 0) {
|
||||
break
|
||||
}
|
||||
b.Kind = BlockFirst
|
||||
b.SetControl(nil)
|
||||
b.ResetControls()
|
||||
b.Aux = nil
|
||||
b.swapSuccessors()
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -195,27 +195,31 @@ func schedule(f *Func) {
|
|||
}
|
||||
}
|
||||
|
||||
if b.Control != nil && b.Control.Op != OpPhi && b.Control.Op != OpArg {
|
||||
// Force the control value to be scheduled at the end,
|
||||
// unless it is a phi value (which must be first).
|
||||
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.
|
||||
score[b.Control.ID] = ScoreControl
|
||||
if c.Op == OpPhi || c.Op == OpArg {
|
||||
continue
|
||||
}
|
||||
score[c.ID] = ScoreControl
|
||||
|
||||
// Schedule values dependent on the control value at the end.
|
||||
// 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 control, just values with a
|
||||
// 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 == b.Control {
|
||||
if a == c {
|
||||
score[v.ID] = ScoreControl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// To put things into a priority queue
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ func shortcircuit(f *Func) {
|
|||
if p.Kind != BlockIf {
|
||||
continue
|
||||
}
|
||||
if p.Control != a {
|
||||
if p.Controls[0] != a {
|
||||
continue
|
||||
}
|
||||
if e.i == 0 {
|
||||
|
|
@ -103,7 +103,7 @@ func shortcircuitBlock(b *Block) bool {
|
|||
// 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.
|
||||
v := b.Control
|
||||
v := b.Controls[0]
|
||||
nval := 1 // the control value
|
||||
swap := false
|
||||
for v.Uses == 1 && v.Block == b && (v.Op == OpCopy || v.Op == OpNot) {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ func TestSizeof(t *testing.T) {
|
|||
_64bit uintptr // size on 64bit platforms
|
||||
}{
|
||||
{Value{}, 72, 112},
|
||||
{Block{}, 152, 288},
|
||||
{Block{}, 156, 296},
|
||||
{LocalSlot{}, 32, 48},
|
||||
{valState{}, 28, 40},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ func tighten(f *Func) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if c := b.Control; c != nil {
|
||||
for _, c := range b.ControlValues() {
|
||||
if !canMove[c.ID] {
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ type Value struct {
|
|||
// Source position
|
||||
Pos src.XPos
|
||||
|
||||
// Use count. Each appearance in Value.Args and Block.Control counts once.
|
||||
// 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)
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ func writebarrier(f *Func) {
|
|||
b.Pos = pos
|
||||
|
||||
// set up control flow for end block
|
||||
bEnd.SetControl(b.Control)
|
||||
bEnd.CopyControls(b)
|
||||
bEnd.Likely = b.Likely
|
||||
for _, e := range b.Succs {
|
||||
bEnd.Succs = append(bEnd.Succs, e)
|
||||
|
|
|
|||
|
|
@ -78,20 +78,20 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
switch next {
|
||||
case b.Succs[0].Block():
|
||||
// if false, jump to b.Succs[1]
|
||||
getValue32(s, b.Control)
|
||||
getValue32(s, b.Controls[0])
|
||||
s.Prog(wasm.AI32Eqz)
|
||||
s.Prog(wasm.AIf)
|
||||
s.Br(obj.AJMP, b.Succs[1].Block())
|
||||
s.Prog(wasm.AEnd)
|
||||
case b.Succs[1].Block():
|
||||
// if true, jump to b.Succs[0]
|
||||
getValue32(s, b.Control)
|
||||
getValue32(s, b.Controls[0])
|
||||
s.Prog(wasm.AIf)
|
||||
s.Br(obj.AJMP, b.Succs[0].Block())
|
||||
s.Prog(wasm.AEnd)
|
||||
default:
|
||||
// if true, jump to b.Succs[0], else jump to b.Succs[1]
|
||||
getValue32(s, b.Control)
|
||||
getValue32(s, b.Controls[0])
|
||||
s.Prog(wasm.AIf)
|
||||
s.Br(obj.AJMP, b.Succs[0].Block())
|
||||
s.Prog(wasm.AEnd)
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ import (
|
|||
// markMoves marks any MOVXconst ops that need to avoid clobbering flags.
|
||||
func ssaMarkMoves(s *gc.SSAGenState, b *ssa.Block) {
|
||||
flive := b.FlagsLiveAtEnd
|
||||
if b.Control != nil && b.Control.Type.IsFlags() {
|
||||
flive = true
|
||||
for _, c := range b.ControlValues() {
|
||||
flive = c.Type.IsFlags() || flive
|
||||
}
|
||||
for i := len(b.Values) - 1; i >= 0; i-- {
|
||||
v := b.Values[i]
|
||||
|
|
@ -952,6 +952,6 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
|
|||
}
|
||||
}
|
||||
default:
|
||||
b.Fatalf("branch not implemented: %s. Control: %s", b.LongString(), b.Control.LongString())
|
||||
b.Fatalf("branch not implemented: %s", b.LongString())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue