Commit 56e0ecc5 authored by Keith Randall's avatar Keith Randall

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: default avatarTodd Neal <todd@tneal.org>
parent cb1f2afc
...@@ -540,7 +540,7 @@ func (s *state) stmt(n *Node) { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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) { ...@@ -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 { ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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 ...@@ -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) { ...@@ -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) { ...@@ -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) { ...@@ -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 ...@@ -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 { ...@@ -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 ...@@ -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 { ...@@ -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) { ...@@ -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])
......
...@@ -97,6 +97,16 @@ func (b *Block) LongString() string { ...@@ -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) {
......
...@@ -294,6 +294,26 @@ func checkFunc(f *Func) { ...@@ -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).
......
...@@ -11,11 +11,11 @@ func copyelim(f *Func) { ...@@ -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) { ...@@ -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) { ...@@ -55,6 +56,8 @@ func copyelimValue(v *Value) {
} }
advance = !advance advance = !advance
} }
v.Args[i] = a v.SetArg(i, a)
changed = true
} }
return changed
} }
...@@ -182,7 +182,7 @@ func cse(f *Func) { ...@@ -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)
} }
} }
} }
......
...@@ -164,6 +164,18 @@ func deadcode(f *Func) { ...@@ -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) { ...@@ -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]
......
...@@ -113,7 +113,7 @@ func flagalloc(f *Func) { ...@@ -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 {
......
...@@ -114,6 +114,9 @@ func (f *Func) freeValue(v *Value) { ...@@ -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 { ...@@ -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) ...@@ -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 ...@@ -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 ...@@ -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 { ...@@ -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 * ...@@ -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 ...@@ -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, ...@@ -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
} }
......
...@@ -168,7 +168,7 @@ func Fun(c *Config, entry string, blocs ...bloc) fun { ...@@ -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 {
......
...@@ -96,7 +96,7 @@ func fuseBlockIf(b *Block) bool { ...@@ -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.
......
...@@ -602,12 +602,15 @@ ...@@ -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
......
...@@ -258,9 +258,9 @@ func genRules(arch arch) { ...@@ -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 ...@@ -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)
......
...@@ -98,10 +98,10 @@ func nilcheckelim(f *Func) { ...@@ -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)
} }
......
...@@ -307,7 +307,7 @@ func prove(f *Func) { ...@@ -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]
} }
......
...@@ -897,6 +897,9 @@ func (s *regAllocState) regalloc(f *Func) { ...@@ -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) { ...@@ -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) { ...@@ -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 { ...@@ -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 { ...@@ -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
} }
......
...@@ -31,7 +31,7 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool) ...@@ -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) ...@@ -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
......
...@@ -5390,7 +5390,7 @@ func rewriteValueAMD64_OpAMD64MOVBQSX(v *Value, config *Config) bool { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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
......
...@@ -7798,8 +7798,6 @@ func rewriteValuegeneric_OpStructSelect(v *Value, config *Config) bool { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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 { ...@@ -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
......
...@@ -36,9 +36,9 @@ func shortcircuit(f *Func) { ...@@ -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) { ...@@ -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) { ...@@ -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]
......
...@@ -22,7 +22,7 @@ func TestSizeof(t *testing.T) { ...@@ -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},
} }
......
...@@ -38,6 +38,9 @@ type Value struct { ...@@ -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) { ...@@ -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) { ...@@ -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]
......
...@@ -48,7 +48,7 @@ func zcse(f *Func) { ...@@ -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)
} }
} }
} }
......
// 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
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment