1
0
mirror of https://github.com/golang/go synced 2024-07-05 09:50:19 +00:00

cmd/compile: keep value use counts in SSA

Keep track of how many uses each Value has.  Each appearance in
Value.Args and in Block.Control counts once.

The number of uses of a value is generically useful to
constrain rewrite rules.  For instance, we might want to
prevent merging index operations into loads if the same
index expression is used lots of times.

But I have one use in particular for which the use count is required.
We must make sure we don't combine ops with loads if the load has
more than one use.  Otherwise, we may split a single load
into multiple loads and that breaks perceived behavior in
the presence of races.  In particular, the load of m.state
in sync/mutex.go:Lock can't be done twice.  (I have a separate
CL which triggers the mutex failure.  This CL has a test which
demonstrates a similar failure.)

Change-Id: Icaafa479239f48632a069d0c3f624e6ebc6b1f0e
Reviewed-on: https://go-review.googlesource.com/20790
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Todd Neal <todd@tneal.org>
This commit is contained in:
Keith Randall 2016-03-15 20:45:50 -07:00
parent cb1f2afc99
commit 56e0ecc5ea
23 changed files with 296 additions and 147 deletions

View File

@ -540,7 +540,7 @@ func (s *state) stmt(n *Node) {
m := s.mem() m := s.mem()
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockExit b.Kind = ssa.BlockExit
b.Control = m b.SetControl(m)
// TODO: never rewrite OPANIC to OCALLFUNC in the // TODO: never rewrite OPANIC to OCALLFUNC in the
// first place. Need to wait until all backends // first place. Need to wait until all backends
// go through SSA. // go through SSA.
@ -920,7 +920,7 @@ func (s *state) exit() *ssa.Block {
m := s.mem() m := s.mem()
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockRet b.Kind = ssa.BlockRet
b.Control = m b.SetControl(m)
return b return b
} }
@ -1795,7 +1795,7 @@ func (s *state) expr(n *Node) *ssa.Value {
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = el b.SetControl(el)
// In theory, we should set b.Likely here based on context. // In theory, we should set b.Likely here based on context.
// However, gc only gives us likeliness hints // However, gc only gives us likeliness hints
// in a single place, for plain OIF statements, // in a single place, for plain OIF statements,
@ -2039,7 +2039,7 @@ func (s *state) expr(n *Node) *ssa.Value {
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Likely = ssa.BranchUnlikely b.Likely = ssa.BranchUnlikely
b.Control = cmp b.SetControl(cmp)
b.AddEdgeTo(grow) b.AddEdgeTo(grow)
b.AddEdgeTo(assign) b.AddEdgeTo(assign)
@ -2143,7 +2143,7 @@ func (s *state) condBranch(cond *Node, yes, no *ssa.Block, likely int8) {
c := s.expr(cond) c := s.expr(cond)
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = c b.SetControl(c)
b.Likely = ssa.BranchPrediction(likely) // gc and ssa both use -1/0/+1 for likeliness b.Likely = ssa.BranchPrediction(likely) // gc and ssa both use -1/0/+1 for likeliness
b.AddEdgeTo(yes) b.AddEdgeTo(yes)
b.AddEdgeTo(no) b.AddEdgeTo(no)
@ -2396,7 +2396,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value {
s.vars[&memVar] = call s.vars[&memVar] = call
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockCall b.Kind = ssa.BlockCall
b.Control = call b.SetControl(call)
b.AddEdgeTo(bNext) b.AddEdgeTo(bNext)
if k == callDefer { if k == callDefer {
// Add recover edge to exit code. // Add recover edge to exit code.
@ -2654,7 +2654,7 @@ func (s *state) nilCheck(ptr *ssa.Value) {
chk := s.newValue2(ssa.OpNilCheck, ssa.TypeVoid, ptr, s.mem()) chk := s.newValue2(ssa.OpNilCheck, ssa.TypeVoid, ptr, s.mem())
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockCheck b.Kind = ssa.BlockCheck
b.Control = chk b.SetControl(chk)
bNext := s.f.NewBlock(ssa.BlockPlain) bNext := s.f.NewBlock(ssa.BlockPlain)
b.AddEdgeTo(bNext) b.AddEdgeTo(bNext)
s.startBlock(bNext) s.startBlock(bNext)
@ -2692,7 +2692,7 @@ func (s *state) sliceBoundsCheck(idx, len *ssa.Value) {
func (s *state) check(cmp *ssa.Value, fn *Node) { func (s *state) check(cmp *ssa.Value, fn *Node) {
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = cmp b.SetControl(cmp)
b.Likely = ssa.BranchLikely b.Likely = ssa.BranchLikely
bNext := s.f.NewBlock(ssa.BlockPlain) bNext := s.f.NewBlock(ssa.BlockPlain)
line := s.peekLine() line := s.peekLine()
@ -2740,7 +2740,7 @@ func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Val
b := s.endBlock() b := s.endBlock()
if !returns { if !returns {
b.Kind = ssa.BlockExit b.Kind = ssa.BlockExit
b.Control = call b.SetControl(call)
call.AuxInt = off call.AuxInt = off
if len(results) > 0 { if len(results) > 0 {
Fatalf("panic call can't have results") Fatalf("panic call can't have results")
@ -2748,7 +2748,7 @@ func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Val
return nil return nil
} }
b.Kind = ssa.BlockCall b.Kind = ssa.BlockCall
b.Control = call b.SetControl(call)
bNext := s.f.NewBlock(ssa.BlockPlain) bNext := s.f.NewBlock(ssa.BlockPlain)
b.AddEdgeTo(bNext) b.AddEdgeTo(bNext)
s.startBlock(bNext) s.startBlock(bNext)
@ -2793,7 +2793,7 @@ func (s *state) insertWBmove(t *Type, left, right *ssa.Value, line int32) {
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Likely = ssa.BranchUnlikely b.Likely = ssa.BranchUnlikely
b.Control = flag b.SetControl(flag)
b.AddEdgeTo(bThen) b.AddEdgeTo(bThen)
b.AddEdgeTo(bElse) b.AddEdgeTo(bElse)
@ -2838,7 +2838,7 @@ func (s *state) insertWBstore(t *Type, left, right *ssa.Value, line int32) {
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Likely = ssa.BranchUnlikely b.Likely = ssa.BranchUnlikely
b.Control = flag b.SetControl(flag)
b.AddEdgeTo(bThen) b.AddEdgeTo(bThen)
b.AddEdgeTo(bElse) b.AddEdgeTo(bElse)
@ -3049,7 +3049,7 @@ func (s *state) slice(t *Type, v, i, j, k *ssa.Value) (p, l, c *ssa.Value) {
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Likely = ssa.BranchLikely b.Likely = ssa.BranchLikely
b.Control = cmp b.SetControl(cmp)
// Generate code for non-zero length slice case. // Generate code for non-zero length slice case.
nz := s.f.NewBlock(ssa.BlockPlain) nz := s.f.NewBlock(ssa.BlockPlain)
@ -3150,7 +3150,7 @@ func (s *state) uintTofloat(cvttab *u2fcvtTab, n *Node, x *ssa.Value, ft, tt *Ty
cmp := s.newValue2(cvttab.geq, Types[TBOOL], x, s.zeroVal(ft)) cmp := s.newValue2(cvttab.geq, Types[TBOOL], x, s.zeroVal(ft))
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = cmp b.SetControl(cmp)
b.Likely = ssa.BranchLikely b.Likely = ssa.BranchLikely
bThen := s.f.NewBlock(ssa.BlockPlain) bThen := s.f.NewBlock(ssa.BlockPlain)
@ -3198,7 +3198,7 @@ func (s *state) referenceTypeBuiltin(n *Node, x *ssa.Value) *ssa.Value {
cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, nilValue) cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, nilValue)
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = cmp b.SetControl(cmp)
b.Likely = ssa.BranchUnlikely b.Likely = ssa.BranchUnlikely
bThen := s.f.NewBlock(ssa.BlockPlain) bThen := s.f.NewBlock(ssa.BlockPlain)
@ -3269,7 +3269,7 @@ func (s *state) floatToUint(cvttab *f2uCvtTab, n *Node, x *ssa.Value, ft, tt *Ty
cmp := s.newValue2(cvttab.ltf, Types[TBOOL], x, twoToThe63) cmp := s.newValue2(cvttab.ltf, Types[TBOOL], x, twoToThe63)
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = cmp b.SetControl(cmp)
b.Likely = ssa.BranchLikely b.Likely = ssa.BranchLikely
bThen := s.f.NewBlock(ssa.BlockPlain) bThen := s.f.NewBlock(ssa.BlockPlain)
@ -3318,7 +3318,7 @@ func (s *state) ifaceType(n *Node, v *ssa.Value) *ssa.Value {
isnonnil := s.newValue2(ssa.OpNeqPtr, Types[TBOOL], tab, s.constNil(byteptr)) isnonnil := s.newValue2(ssa.OpNeqPtr, Types[TBOOL], tab, s.constNil(byteptr))
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = isnonnil b.SetControl(isnonnil)
b.Likely = ssa.BranchLikely b.Likely = ssa.BranchLikely
bLoad := s.f.NewBlock(ssa.BlockPlain) bLoad := s.f.NewBlock(ssa.BlockPlain)
@ -3360,7 +3360,7 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) {
cond := s.newValue2(ssa.OpEqPtr, Types[TBOOL], typ, target) cond := s.newValue2(ssa.OpEqPtr, Types[TBOOL], typ, target)
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = cond b.SetControl(cond)
b.Likely = ssa.BranchLikely b.Likely = ssa.BranchLikely
byteptr := Ptrto(Types[TUINT8]) byteptr := Ptrto(Types[TUINT8])

View File

@ -97,6 +97,16 @@ func (b *Block) LongString() string {
return s return s
} }
func (b *Block) SetControl(v *Value) {
if w := b.Control; w != nil {
w.Uses--
}
b.Control = v
if v != nil {
v.Uses++
}
}
// AddEdgeTo adds an edge from block b to block c. Used during building of the // AddEdgeTo adds an edge from block b to block c. Used during building of the
// SSA graph; do not use on an already-completed SSA graph. // SSA graph; do not use on an already-completed SSA graph.
func (b *Block) AddEdgeTo(c *Block) { func (b *Block) AddEdgeTo(c *Block) {

View File

@ -294,6 +294,26 @@ func checkFunc(f *Func) {
} }
} }
} }
// Check use counts
uses := make([]int32, f.NumValues())
for _, b := range f.Blocks {
for _, v := range b.Values {
for _, a := range v.Args {
uses[a.ID]++
}
}
if b.Control != nil {
uses[b.Control.ID]++
}
}
for _, b := range f.Blocks {
for _, v := range b.Values {
if v.Uses != uses[v.ID] {
f.Fatalf("%s has %d uses, but has Uses=%d", v, uses[v.ID], v.Uses)
}
}
}
} }
// domCheck reports whether x dominates y (including x==y). // domCheck reports whether x dominates y (including x==y).

View File

@ -11,11 +11,11 @@ func copyelim(f *Func) {
copyelimValue(v) copyelimValue(v)
} }
v := b.Control v := b.Control
if v != nil { if v != nil && v.Op == OpCopy {
for v.Op == OpCopy { for v.Op == OpCopy {
v = v.Args[0] v = v.Args[0]
} }
b.Control = v b.SetControl(v)
} }
} }
@ -34,8 +34,9 @@ func copyelim(f *Func) {
} }
} }
func copyelimValue(v *Value) { func copyelimValue(v *Value) bool {
// elide any copies generated during rewriting // elide any copies generated during rewriting
changed := false
for i, a := range v.Args { for i, a := range v.Args {
if a.Op != OpCopy { if a.Op != OpCopy {
continue continue
@ -55,6 +56,8 @@ func copyelimValue(v *Value) {
} }
advance = !advance advance = !advance
} }
v.Args[i] = a v.SetArg(i, a)
changed = true
} }
return changed
} }

View File

@ -182,7 +182,7 @@ func cse(f *Func) {
// them appropriately, so don't mess with them here. // them appropriately, so don't mess with them here.
continue continue
} }
b.Control = x b.SetControl(x)
} }
} }
} }

View File

@ -164,6 +164,18 @@ func deadcode(f *Func) {
} }
f.Names = f.Names[:i] f.Names = f.Names[:i]
// Unlink values.
for _, b := range f.Blocks {
if !reachable[b.ID] {
b.SetControl(nil)
}
for _, v := range b.Values {
if !live[v.ID] {
v.resetArgs()
}
}
}
// Remove dead values from blocks' value list. Return dead // Remove dead values from blocks' value list. Return dead
// values to the allocator. // values to the allocator.
for _, b := range f.Blocks { for _, b := range f.Blocks {
@ -231,6 +243,7 @@ func (b *Block) removePred(p *Block) {
if v.Op != OpPhi { if v.Op != OpPhi {
continue continue
} }
v.Args[i].Uses--
v.Args[i] = v.Args[n] v.Args[i] = v.Args[n]
v.Args[n] = nil // aid GC v.Args[n] = nil // aid GC
v.Args = v.Args[:n] v.Args = v.Args[:n]

View File

@ -113,7 +113,7 @@ func flagalloc(f *Func) {
if v := b.Control; v != nil && v != flag && v.Type.IsFlags() { if v := b.Control; v != nil && v != flag && v.Type.IsFlags() {
// Recalculate control value. // Recalculate control value.
c := v.copyInto(b) c := v.copyInto(b)
b.Control = c b.SetControl(c)
flag = v flag = v
} }
if v := end[b.ID]; v != nil && v != flag { if v := end[b.ID]; v != nil && v != flag {

View File

@ -114,6 +114,9 @@ func (f *Func) freeValue(v *Value) {
if v.Block == nil { if v.Block == nil {
f.Fatalf("trying to free an already freed value") f.Fatalf("trying to free an already freed value")
} }
if v.Uses != 0 {
f.Fatalf("value %s still has %d uses", v, v.Uses)
}
// Clear everything but ID (which we reuse). // Clear everything but ID (which we reuse).
id := v.ID id := v.ID
@ -217,6 +220,7 @@ func (b *Block) NewValue1(line int32, op Op, t Type, arg *Value) *Value {
v.AuxInt = 0 v.AuxInt = 0
v.Args = v.argstorage[:1] v.Args = v.argstorage[:1]
v.argstorage[0] = arg v.argstorage[0] = arg
arg.Uses++
return v return v
} }
@ -226,6 +230,7 @@ func (b *Block) NewValue1I(line int32, op Op, t Type, auxint int64, arg *Value)
v.AuxInt = auxint v.AuxInt = auxint
v.Args = v.argstorage[:1] v.Args = v.argstorage[:1]
v.argstorage[0] = arg v.argstorage[0] = arg
arg.Uses++
return v return v
} }
@ -236,6 +241,7 @@ func (b *Block) NewValue1A(line int32, op Op, t Type, aux interface{}, arg *Valu
v.Aux = aux v.Aux = aux
v.Args = v.argstorage[:1] v.Args = v.argstorage[:1]
v.argstorage[0] = arg v.argstorage[0] = arg
arg.Uses++
return v return v
} }
@ -246,6 +252,7 @@ func (b *Block) NewValue1IA(line int32, op Op, t Type, auxint int64, aux interfa
v.Aux = aux v.Aux = aux
v.Args = v.argstorage[:1] v.Args = v.argstorage[:1]
v.argstorage[0] = arg v.argstorage[0] = arg
arg.Uses++
return v return v
} }
@ -256,6 +263,8 @@ func (b *Block) NewValue2(line int32, op Op, t Type, arg0, arg1 *Value) *Value {
v.Args = v.argstorage[:2] v.Args = v.argstorage[:2]
v.argstorage[0] = arg0 v.argstorage[0] = arg0
v.argstorage[1] = arg1 v.argstorage[1] = arg1
arg0.Uses++
arg1.Uses++
return v return v
} }
@ -266,6 +275,8 @@ func (b *Block) NewValue2I(line int32, op Op, t Type, auxint int64, arg0, arg1 *
v.Args = v.argstorage[:2] v.Args = v.argstorage[:2]
v.argstorage[0] = arg0 v.argstorage[0] = arg0
v.argstorage[1] = arg1 v.argstorage[1] = arg1
arg0.Uses++
arg1.Uses++
return v return v
} }
@ -274,6 +285,9 @@ func (b *Block) NewValue3(line int32, op Op, t Type, arg0, arg1, arg2 *Value) *V
v := b.Func.newValue(op, t, b, line) v := b.Func.newValue(op, t, b, line)
v.AuxInt = 0 v.AuxInt = 0
v.Args = []*Value{arg0, arg1, arg2} v.Args = []*Value{arg0, arg1, arg2}
arg0.Uses++
arg1.Uses++
arg2.Uses++
return v return v
} }
@ -282,6 +296,9 @@ func (b *Block) NewValue3I(line int32, op Op, t Type, auxint int64, arg0, arg1,
v := b.Func.newValue(op, t, b, line) v := b.Func.newValue(op, t, b, line)
v.AuxInt = auxint v.AuxInt = auxint
v.Args = []*Value{arg0, arg1, arg2} v.Args = []*Value{arg0, arg1, arg2}
arg0.Uses++
arg1.Uses++
arg2.Uses++
return v return v
} }

View File

@ -168,7 +168,7 @@ func Fun(c *Config, entry string, blocs ...bloc) fun {
if !ok { if !ok {
f.Fatalf("control value for block %s missing", bloc.name) f.Fatalf("control value for block %s missing", bloc.name)
} }
b.Control = cval b.SetControl(cval)
} }
// Fill in args. // Fill in args.
for _, valu := range bloc.valus { for _, valu := range bloc.valus {

View File

@ -96,7 +96,7 @@ func fuseBlockIf(b *Block) bool {
ss.removePred(s1) ss.removePred(s1)
} }
b.Kind = BlockPlain b.Kind = BlockPlain
b.Control = nil b.SetControl(nil)
b.Succs = append(b.Succs[:0], ss) b.Succs = append(b.Succs[:0], ss)
// Trash the empty blocks s0 & s1. // Trash the empty blocks s0 & s1.

View File

@ -602,12 +602,15 @@
// as the original load. If not, we end up making a value with // as the original load. If not, we end up making a value with
// memory type live in two different blocks, which can lead to // memory type live in two different blocks, which can lead to
// multiple memory values alive simultaneously. // multiple memory values alive simultaneously.
(MOVBQSX (MOVBload [off] {sym} ptr mem)) -> @v.Args[0].Block (MOVBQSXload <v.Type> [off] {sym} ptr mem) // Make sure we don't combine these ops if the load has another use.
(MOVBQZX (MOVBload [off] {sym} ptr mem)) -> @v.Args[0].Block (MOVBQZXload <v.Type> [off] {sym} ptr mem) // This prevents a single load from being split into multiple loads
(MOVWQSX (MOVWload [off] {sym} ptr mem)) -> @v.Args[0].Block (MOVWQSXload <v.Type> [off] {sym} ptr mem) // which then might return different values. See test/atomicload.go.
(MOVWQZX (MOVWload [off] {sym} ptr mem)) -> @v.Args[0].Block (MOVWQZXload <v.Type> [off] {sym} ptr mem) (MOVBQSX (MOVBload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
(MOVLQSX (MOVLload [off] {sym} ptr mem)) -> @v.Args[0].Block (MOVLQSXload <v.Type> [off] {sym} ptr mem) (MOVBQZX (MOVBload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVBQZXload <v.Type> [off] {sym} ptr mem)
(MOVLQZX (MOVLload [off] {sym} ptr mem)) -> @v.Args[0].Block (MOVLQZXload <v.Type> [off] {sym} ptr mem) (MOVWQSX (MOVWload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
(MOVWQZX (MOVWload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVWQZXload <v.Type> [off] {sym} ptr mem)
(MOVLQSX (MOVLload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVLQSXload <v.Type> [off] {sym} ptr mem)
(MOVLQZX (MOVLload [off] {sym} ptr mem)) && v.Args[0].Uses == 1 -> @v.Args[0].Block (MOVLQZXload <v.Type> [off] {sym} ptr mem)
// replace load from same location as preceding store with copy // replace load from same location as preceding store with copy
(MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x (MOVBload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x

View File

@ -258,9 +258,9 @@ func genRules(arch arch) {
fmt.Fprintf(w, "b.Kind = %s\n", blockName(t[0], arch)) fmt.Fprintf(w, "b.Kind = %s\n", blockName(t[0], arch))
if t[1] == "nil" { if t[1] == "nil" {
fmt.Fprintf(w, "b.Control = nil\n") fmt.Fprintf(w, "b.SetControl(nil)\n")
} else { } else {
fmt.Fprintf(w, "b.Control = %s\n", genResult0(w, arch, t[1], new(int), false, false)) fmt.Fprintf(w, "b.SetControl(%s)\n", genResult0(w, arch, t[1], new(int), false, false))
} }
if len(newsuccs) < len(succs) { if len(newsuccs) < len(succs) {
fmt.Fprintf(w, "b.Succs = b.Succs[:%d]\n", len(newsuccs)) fmt.Fprintf(w, "b.Succs = b.Succs[:%d]\n", len(newsuccs))
@ -486,7 +486,7 @@ func genResult0(w io.Writer, arch arch, result string, alloc *int, top, move boo
v = fmt.Sprintf("v%d", *alloc) v = fmt.Sprintf("v%d", *alloc)
*alloc++ *alloc++
fmt.Fprintf(w, "%s := b.NewValue0(v.Line, %s, %s)\n", v, opName(s[0], arch), opType) fmt.Fprintf(w, "%s := b.NewValue0(v.Line, %s, %s)\n", v, opName(s[0], arch), opType)
if move { if move && top {
// Rewrite original into a copy // Rewrite original into a copy
fmt.Fprintf(w, "v.reset(OpCopy)\n") fmt.Fprintf(w, "v.reset(OpCopy)\n")
fmt.Fprintf(w, "v.AddArg(%s)\n", v) fmt.Fprintf(w, "v.AddArg(%s)\n", v)

View File

@ -98,10 +98,10 @@ func nilcheckelim(f *Func) {
switch node.block.Kind { switch node.block.Kind {
case BlockIf: case BlockIf:
node.block.Kind = BlockFirst node.block.Kind = BlockFirst
node.block.Control = nil node.block.SetControl(nil)
case BlockCheck: case BlockCheck:
node.block.Kind = BlockPlain node.block.Kind = BlockPlain
node.block.Control = nil node.block.SetControl(nil)
default: default:
f.Fatalf("bad block kind in nilcheck %s", node.block.Kind) f.Fatalf("bad block kind in nilcheck %s", node.block.Kind)
} }

View File

@ -307,7 +307,7 @@ func prove(f *Func) {
if succ != unknown { if succ != unknown {
b := node.block b := node.block
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
if succ == negative { if succ == negative {
b.Succs[0], b.Succs[1] = b.Succs[1], b.Succs[0] b.Succs[0], b.Succs[1] = b.Succs[1], b.Succs[0]
} }

View File

@ -897,6 +897,9 @@ func (s *regAllocState) regalloc(f *Func) {
// Value is rematerializeable, don't issue it here. // Value is rematerializeable, don't issue it here.
// It will get issued just before each use (see // It will get issued just before each use (see
// allocValueToReg). // allocValueToReg).
for _, a := range v.Args {
a.Uses--
}
s.advanceUses(v) s.advanceUses(v)
continue continue
} }
@ -949,7 +952,7 @@ func (s *regAllocState) regalloc(f *Func) {
// Issue the Value itself. // Issue the Value itself.
for i, a := range args { for i, a := range args {
v.Args[i] = a // use register version of arguments v.SetArg(i, a) // use register version of arguments
} }
b.Values = append(b.Values, v) b.Values = append(b.Values, v)
@ -1123,6 +1126,7 @@ func (s *regAllocState) regalloc(f *Func) {
// Constants, SP, SB, ... // Constants, SP, SB, ...
continue continue
} }
spill.Args[0].Uses--
f.freeValue(spill) f.freeValue(spill)
} }
for _, b := range f.Blocks { for _, b := range f.Blocks {
@ -1333,7 +1337,9 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool {
// Value is already in the correct place. // Value is already in the correct place.
e.contents[loc] = contentRecord{vid, occupant.c, true} e.contents[loc] = contentRecord{vid, occupant.c, true}
if splice != nil { if splice != nil {
(*splice).Uses--
*splice = occupant.c *splice = occupant.c
occupant.c.Uses++
} }
// Note: if splice==nil then c will appear dead. This is // Note: if splice==nil then c will appear dead. This is
// non-SSA formed code, so be careful after this pass not to run // non-SSA formed code, so be careful after this pass not to run
@ -1430,7 +1436,9 @@ func (e *edgeState) processDest(loc Location, vid ID, splice **Value) bool {
} }
e.set(loc, vid, x, true) e.set(loc, vid, x, true)
if splice != nil { if splice != nil {
(*splice).Uses--
*splice = x *splice = x
x.Uses++
} }
return true return true
} }

View File

@ -31,7 +31,7 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool)
} }
if b.Control != nil && b.Control.Op == OpCopy { if b.Control != nil && b.Control.Op == OpCopy {
for b.Control.Op == OpCopy { for b.Control.Op == OpCopy {
b.Control = b.Control.Args[0] b.SetControl(b.Control.Args[0])
} }
} }
curb = b curb = b
@ -40,7 +40,7 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool)
} }
curb = nil curb = nil
for _, v := range b.Values { for _, v := range b.Values {
copyelimValue(v) change = copyelimValue(v) || change
change = phielimValue(v) || change change = phielimValue(v) || change
// apply rewrite function // apply rewrite function

View File

@ -5390,7 +5390,7 @@ func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (MOVBQSX (MOVBload [off] {sym} ptr mem)) // match: (MOVBQSX (MOVBload [off] {sym} ptr mem))
// cond: // cond: v.Args[0].Uses == 1
// result: @v.Args[0].Block (MOVBQSXload <v.Type> [off] {sym} ptr mem) // result: @v.Args[0].Block (MOVBQSXload <v.Type> [off] {sym} ptr mem)
for { for {
if v.Args[0].Op != OpAMD64MOVBload { if v.Args[0].Op != OpAMD64MOVBload {
@ -5400,6 +5400,9 @@ func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value, config *Config) bool {
sym := v.Args[0].Aux sym := v.Args[0].Aux
ptr := v.Args[0].Args[0] ptr := v.Args[0].Args[0]
mem := v.Args[0].Args[1] mem := v.Args[0].Args[1]
if !(v.Args[0].Uses == 1) {
break
}
b = v.Args[0].Block b = v.Args[0].Block
v0 := b.NewValue0(v.Line, OpAMD64MOVBQSXload, v.Type) v0 := b.NewValue0(v.Line, OpAMD64MOVBQSXload, v.Type)
v.reset(OpCopy) v.reset(OpCopy)
@ -5461,7 +5464,7 @@ func rewriteValueAMD64_OpAMD64MOVBQZX(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (MOVBQZX (MOVBload [off] {sym} ptr mem)) // match: (MOVBQZX (MOVBload [off] {sym} ptr mem))
// cond: // cond: v.Args[0].Uses == 1
// result: @v.Args[0].Block (MOVBQZXload <v.Type> [off] {sym} ptr mem) // result: @v.Args[0].Block (MOVBQZXload <v.Type> [off] {sym} ptr mem)
for { for {
if v.Args[0].Op != OpAMD64MOVBload { if v.Args[0].Op != OpAMD64MOVBload {
@ -5471,6 +5474,9 @@ func rewriteValueAMD64_OpAMD64MOVBQZX(v *Value, config *Config) bool {
sym := v.Args[0].Aux sym := v.Args[0].Aux
ptr := v.Args[0].Args[0] ptr := v.Args[0].Args[0]
mem := v.Args[0].Args[1] mem := v.Args[0].Args[1]
if !(v.Args[0].Uses == 1) {
break
}
b = v.Args[0].Block b = v.Args[0].Block
v0 := b.NewValue0(v.Line, OpAMD64MOVBQZXload, v.Type) v0 := b.NewValue0(v.Line, OpAMD64MOVBQZXload, v.Type)
v.reset(OpCopy) v.reset(OpCopy)
@ -6051,7 +6057,7 @@ func rewriteValueAMD64_OpAMD64MOVLQSX(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (MOVLQSX (MOVLload [off] {sym} ptr mem)) // match: (MOVLQSX (MOVLload [off] {sym} ptr mem))
// cond: // cond: v.Args[0].Uses == 1
// result: @v.Args[0].Block (MOVLQSXload <v.Type> [off] {sym} ptr mem) // result: @v.Args[0].Block (MOVLQSXload <v.Type> [off] {sym} ptr mem)
for { for {
if v.Args[0].Op != OpAMD64MOVLload { if v.Args[0].Op != OpAMD64MOVLload {
@ -6061,6 +6067,9 @@ func rewriteValueAMD64_OpAMD64MOVLQSX(v *Value, config *Config) bool {
sym := v.Args[0].Aux sym := v.Args[0].Aux
ptr := v.Args[0].Args[0] ptr := v.Args[0].Args[0]
mem := v.Args[0].Args[1] mem := v.Args[0].Args[1]
if !(v.Args[0].Uses == 1) {
break
}
b = v.Args[0].Block b = v.Args[0].Block
v0 := b.NewValue0(v.Line, OpAMD64MOVLQSXload, v.Type) v0 := b.NewValue0(v.Line, OpAMD64MOVLQSXload, v.Type)
v.reset(OpCopy) v.reset(OpCopy)
@ -6122,7 +6131,7 @@ func rewriteValueAMD64_OpAMD64MOVLQZX(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (MOVLQZX (MOVLload [off] {sym} ptr mem)) // match: (MOVLQZX (MOVLload [off] {sym} ptr mem))
// cond: // cond: v.Args[0].Uses == 1
// result: @v.Args[0].Block (MOVLQZXload <v.Type> [off] {sym} ptr mem) // result: @v.Args[0].Block (MOVLQZXload <v.Type> [off] {sym} ptr mem)
for { for {
if v.Args[0].Op != OpAMD64MOVLload { if v.Args[0].Op != OpAMD64MOVLload {
@ -6132,6 +6141,9 @@ func rewriteValueAMD64_OpAMD64MOVLQZX(v *Value, config *Config) bool {
sym := v.Args[0].Aux sym := v.Args[0].Aux
ptr := v.Args[0].Args[0] ptr := v.Args[0].Args[0]
mem := v.Args[0].Args[1] mem := v.Args[0].Args[1]
if !(v.Args[0].Uses == 1) {
break
}
b = v.Args[0].Block b = v.Args[0].Block
v0 := b.NewValue0(v.Line, OpAMD64MOVLQZXload, v.Type) v0 := b.NewValue0(v.Line, OpAMD64MOVLQZXload, v.Type)
v.reset(OpCopy) v.reset(OpCopy)
@ -7652,7 +7664,7 @@ func rewriteValueAMD64_OpAMD64MOVWQSX(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (MOVWQSX (MOVWload [off] {sym} ptr mem)) // match: (MOVWQSX (MOVWload [off] {sym} ptr mem))
// cond: // cond: v.Args[0].Uses == 1
// result: @v.Args[0].Block (MOVWQSXload <v.Type> [off] {sym} ptr mem) // result: @v.Args[0].Block (MOVWQSXload <v.Type> [off] {sym} ptr mem)
for { for {
if v.Args[0].Op != OpAMD64MOVWload { if v.Args[0].Op != OpAMD64MOVWload {
@ -7662,6 +7674,9 @@ func rewriteValueAMD64_OpAMD64MOVWQSX(v *Value, config *Config) bool {
sym := v.Args[0].Aux sym := v.Args[0].Aux
ptr := v.Args[0].Args[0] ptr := v.Args[0].Args[0]
mem := v.Args[0].Args[1] mem := v.Args[0].Args[1]
if !(v.Args[0].Uses == 1) {
break
}
b = v.Args[0].Block b = v.Args[0].Block
v0 := b.NewValue0(v.Line, OpAMD64MOVWQSXload, v.Type) v0 := b.NewValue0(v.Line, OpAMD64MOVWQSXload, v.Type)
v.reset(OpCopy) v.reset(OpCopy)
@ -7723,7 +7738,7 @@ func rewriteValueAMD64_OpAMD64MOVWQZX(v *Value, config *Config) bool {
b := v.Block b := v.Block
_ = b _ = b
// match: (MOVWQZX (MOVWload [off] {sym} ptr mem)) // match: (MOVWQZX (MOVWload [off] {sym} ptr mem))
// cond: // cond: v.Args[0].Uses == 1
// result: @v.Args[0].Block (MOVWQZXload <v.Type> [off] {sym} ptr mem) // result: @v.Args[0].Block (MOVWQZXload <v.Type> [off] {sym} ptr mem)
for { for {
if v.Args[0].Op != OpAMD64MOVWload { if v.Args[0].Op != OpAMD64MOVWload {
@ -7733,6 +7748,9 @@ func rewriteValueAMD64_OpAMD64MOVWQZX(v *Value, config *Config) bool {
sym := v.Args[0].Aux sym := v.Args[0].Aux
ptr := v.Args[0].Args[0] ptr := v.Args[0].Args[0]
mem := v.Args[0].Args[1] mem := v.Args[0].Args[1]
if !(v.Args[0].Uses == 1) {
break
}
b = v.Args[0].Block b = v.Args[0].Block
v0 := b.NewValue0(v.Line, OpAMD64MOVWQZXload, v.Type) v0 := b.NewValue0(v.Line, OpAMD64MOVWQZXload, v.Type)
v.reset(OpCopy) v.reset(OpCopy)
@ -14375,7 +14393,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64EQ b.Kind = BlockAMD64EQ
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14391,7 +14409,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14407,7 +14425,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14424,7 +14442,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14441,7 +14459,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14458,7 +14476,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14477,7 +14495,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64LE b.Kind = BlockAMD64LE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14493,7 +14511,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14509,7 +14527,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14526,7 +14544,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14543,7 +14561,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14559,7 +14577,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14577,7 +14595,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64LT b.Kind = BlockAMD64LT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14593,7 +14611,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14610,7 +14628,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14627,7 +14645,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -14644,7 +14662,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14660,7 +14678,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14678,7 +14696,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64LT b.Kind = BlockAMD64LT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14695,7 +14713,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64LE b.Kind = BlockAMD64LE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14712,7 +14730,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64GT b.Kind = BlockAMD64GT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14729,7 +14747,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64GE b.Kind = BlockAMD64GE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14746,7 +14764,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64EQ b.Kind = BlockAMD64EQ
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14763,7 +14781,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64NE b.Kind = BlockAMD64NE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14780,7 +14798,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64ULT b.Kind = BlockAMD64ULT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14797,7 +14815,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64ULE b.Kind = BlockAMD64ULE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14814,7 +14832,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGT b.Kind = BlockAMD64UGT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14831,7 +14849,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGE b.Kind = BlockAMD64UGE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14848,7 +14866,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGT b.Kind = BlockAMD64UGT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14865,7 +14883,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGE b.Kind = BlockAMD64UGE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14882,7 +14900,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64EQF b.Kind = BlockAMD64EQF
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14899,7 +14917,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64NEF b.Kind = BlockAMD64NEF
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14916,7 +14934,7 @@ func rewriteBlockAMD64(b *Block) bool {
v0 := b.NewValue0(v.Line, OpAMD64TESTB, TypeFlags) v0 := b.NewValue0(v.Line, OpAMD64TESTB, TypeFlags)
v0.AddArg(cond) v0.AddArg(cond)
v0.AddArg(cond) v0.AddArg(cond)
b.Control = v0 b.SetControl(v0)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14934,7 +14952,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64GE b.Kind = BlockAMD64GE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14950,7 +14968,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14966,7 +14984,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14982,7 +15000,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -14998,7 +15016,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15015,7 +15033,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15034,7 +15052,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64GT b.Kind = BlockAMD64GT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15050,7 +15068,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15067,7 +15085,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15083,7 +15101,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15099,7 +15117,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15116,7 +15134,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15138,7 +15156,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64LT b.Kind = BlockAMD64LT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15158,7 +15176,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64LE b.Kind = BlockAMD64LE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15178,7 +15196,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64GT b.Kind = BlockAMD64GT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15198,7 +15216,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64GE b.Kind = BlockAMD64GE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15218,7 +15236,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64EQ b.Kind = BlockAMD64EQ
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15238,7 +15256,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64NE b.Kind = BlockAMD64NE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15258,7 +15276,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64ULT b.Kind = BlockAMD64ULT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15278,7 +15296,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64ULE b.Kind = BlockAMD64ULE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15298,7 +15316,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGT b.Kind = BlockAMD64UGT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15318,7 +15336,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGE b.Kind = BlockAMD64UGE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15338,7 +15356,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGT b.Kind = BlockAMD64UGT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15358,7 +15376,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGE b.Kind = BlockAMD64UGE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15378,7 +15396,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64EQF b.Kind = BlockAMD64EQF
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15398,7 +15416,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64NEF b.Kind = BlockAMD64NEF
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15415,7 +15433,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64NE b.Kind = BlockAMD64NE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15431,7 +15449,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15448,7 +15466,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15464,7 +15482,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15480,7 +15498,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15496,7 +15514,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15514,7 +15532,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64ULE b.Kind = BlockAMD64ULE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15530,7 +15548,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15546,7 +15564,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15563,7 +15581,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15579,7 +15597,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15596,7 +15614,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15614,7 +15632,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64ULT b.Kind = BlockAMD64ULT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15630,7 +15648,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15647,7 +15665,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15664,7 +15682,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15680,7 +15698,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15697,7 +15715,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15715,7 +15733,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGE b.Kind = BlockAMD64UGE
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15731,7 +15749,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15747,7 +15765,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15763,7 +15781,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15780,7 +15798,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15796,7 +15814,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15815,7 +15833,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockAMD64UGT b.Kind = BlockAMD64UGT
b.Control = cmp b.SetControl(cmp)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15831,7 +15849,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15848,7 +15866,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15864,7 +15882,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -15881,7 +15899,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -15897,7 +15915,7 @@ func rewriteBlockAMD64(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1

View File

@ -7798,8 +7798,6 @@ func rewriteValuegeneric_OpStructSelect(v *Value, config *Config) bool {
v.reset(OpCopy) v.reset(OpCopy)
v.AddArg(v0) v.AddArg(v0)
v1 := b.NewValue0(v.Line, OpOffPtr, v.Type.PtrTo()) v1 := b.NewValue0(v.Line, OpOffPtr, v.Type.PtrTo())
v.reset(OpCopy)
v.AddArg(v1)
v1.AuxInt = t.FieldOff(int(i)) v1.AuxInt = t.FieldOff(int(i))
v1.AddArg(ptr) v1.AddArg(ptr)
v0.AddArg(v1) v0.AddArg(v1)
@ -8642,7 +8640,7 @@ func rewriteBlockgeneric(b *Block) bool {
} }
next := b.Succs[0] next := b.Succs[0]
b.Kind = BlockPlain b.Kind = BlockPlain
b.Control = nil b.SetControl(nil)
b.Succs[0] = next b.Succs[0] = next
b.Likely = BranchUnknown b.Likely = BranchUnknown
return true return true
@ -8660,7 +8658,7 @@ func rewriteBlockgeneric(b *Block) bool {
yes := b.Succs[0] yes := b.Succs[0]
no := b.Succs[1] no := b.Succs[1]
b.Kind = BlockIf b.Kind = BlockIf
b.Control = cond b.SetControl(cond)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1
@ -8681,7 +8679,7 @@ func rewriteBlockgeneric(b *Block) bool {
break break
} }
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = yes b.Succs[0] = yes
b.Succs[1] = no b.Succs[1] = no
return true return true
@ -8701,7 +8699,7 @@ func rewriteBlockgeneric(b *Block) bool {
break break
} }
b.Kind = BlockFirst b.Kind = BlockFirst
b.Control = nil b.SetControl(nil)
b.Succs[0] = no b.Succs[0] = no
b.Succs[1] = yes b.Succs[1] = yes
b.Likely *= -1 b.Likely *= -1

View File

@ -36,9 +36,9 @@ func shortcircuit(f *Func) {
continue continue
} }
if p.Succs[0] == b { if p.Succs[0] == b {
v.Args[i] = ct v.SetArg(i, ct)
} else { } else {
v.Args[i] = cf v.SetArg(i, cf)
} }
} }
} }
@ -111,7 +111,7 @@ func shortcircuit(f *Func) {
if w.Op != OpPhi { if w.Op != OpPhi {
continue continue
} }
w.Args = append(w.Args, w.Args[j]) w.AddArg(w.Args[j])
} }
// Fix up b to have one less predecessor. // Fix up b to have one less predecessor.
@ -119,6 +119,7 @@ func shortcircuit(f *Func) {
b.Preds[i] = b.Preds[n] b.Preds[i] = b.Preds[n]
b.Preds[n] = nil b.Preds[n] = nil
b.Preds = b.Preds[:n] b.Preds = b.Preds[:n]
v.Args[i].Uses--
v.Args[i] = v.Args[n] v.Args[i] = v.Args[n]
v.Args[n] = nil v.Args[n] = nil
v.Args = v.Args[:n] v.Args = v.Args[:n]

View File

@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) {
_32bit uintptr // size on 32bit platforms _32bit uintptr // size on 32bit platforms
_64bit uintptr // size on 64bit platforms _64bit uintptr // size on 64bit platforms
}{ }{
{Value{}, 64, 112}, {Value{}, 68, 112},
{Block{}, 124, 232}, {Block{}, 124, 232},
} }

View File

@ -38,6 +38,9 @@ type Value struct {
// Source line number // Source line number
Line int32 Line int32
// Use count. Each appearance in Value.Args and Block.Control counts once.
Uses int32
// Storage for the first three args // Storage for the first three args
argstorage [3]*Value argstorage [3]*Value
} }
@ -162,17 +165,24 @@ func (v *Value) AddArg(w *Value) {
v.resetArgs() // use argstorage v.resetArgs() // use argstorage
} }
v.Args = append(v.Args, w) v.Args = append(v.Args, w)
w.Uses++
} }
func (v *Value) AddArgs(a ...*Value) { func (v *Value) AddArgs(a ...*Value) {
if v.Args == nil { if v.Args == nil {
v.resetArgs() // use argstorage v.resetArgs() // use argstorage
} }
v.Args = append(v.Args, a...) v.Args = append(v.Args, a...)
for _, x := range a {
x.Uses++
}
} }
func (v *Value) SetArg(i int, w *Value) { func (v *Value) SetArg(i int, w *Value) {
v.Args[i].Uses--
v.Args[i] = w v.Args[i] = w
w.Uses++
} }
func (v *Value) RemoveArg(i int) { func (v *Value) RemoveArg(i int) {
v.Args[i].Uses--
copy(v.Args[i:], v.Args[i+1:]) copy(v.Args[i:], v.Args[i+1:])
v.Args[len(v.Args)-1] = nil // aid GC v.Args[len(v.Args)-1] = nil // aid GC
v.Args = v.Args[:len(v.Args)-1] v.Args = v.Args[:len(v.Args)-1]
@ -188,6 +198,9 @@ func (v *Value) SetArgs2(a *Value, b *Value) {
} }
func (v *Value) resetArgs() { func (v *Value) resetArgs() {
for _, a := range v.Args {
a.Uses--
}
v.argstorage[0] = nil v.argstorage[0] = nil
v.argstorage[1] = nil v.argstorage[1] = nil
v.Args = v.argstorage[:0] v.Args = v.argstorage[:0]

View File

@ -48,7 +48,7 @@ func zcse(f *Func) {
if opcodeTable[a.Op].argLen == 0 { if opcodeTable[a.Op].argLen == 0 {
key := vkey{a.Op, keyFor(a), a.Aux, typeStr(a)} key := vkey{a.Op, keyFor(a), a.Aux, typeStr(a)}
if rv, ok := vals[key]; ok { if rv, ok := vals[key]; ok {
v.Args[i] = rv v.SetArg(i, rv)
} }
} }
} }

45
test/atomicload.go Normal file
View File

@ -0,0 +1,45 @@
// run
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Check that we do loads exactly once. The SSA backend
// once tried to do the load in f twice, once sign extended
// and once zero extended. This can cause problems in
// racy code, particularly sync/mutex.
package main
func f(p *byte) bool {
x := *p
a := int64(int8(x))
b := int64(uint8(x))
return a == b
}
func main() {
var x byte
const N = 1000000
c := make(chan struct{})
go func() {
for i := 0; i < N; i++ {
x = 1
}
c <- struct{}{}
}()
go func() {
for i := 0; i < N; i++ {
x = 2
}
c <- struct{}{}
}()
for i := 0; i < N; i++ {
if !f(&x) {
panic("non-atomic load!")
}
}
<-c
<-c
}