Commit 217c2849 authored by Keith Randall's avatar Keith Randall

cmd/compile: combine stores into larger widths

Combine stores into larger widths when it is safe to do so.

Add clobber() function so stray dead uses do not impede the
above rewrites.

Fix bug in loads where all intermediate values depending on
a small load (not just the load itself) must have no other uses.
We really need the small load to be dead after the rewrite..

Fixes #14267

Change-Id: Ib25666cb19777f65082c76238fba51a76beb5d74
Reviewed-on: https://go-review.googlesource.com/22326
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: default avatarTodd Neal <todd@tneal.org>
parent a3703618
...@@ -12,7 +12,7 @@ package main ...@@ -12,7 +12,7 @@ package main
import "fmt" import "fmt"
//go:noinline //go:noinline
func read(b []byte) (uint16, uint16) { func read1(b []byte) (uint16, uint16) {
// There is only a single read of b[0]. The two // There is only a single read of b[0]. The two
// returned values must have the same low byte. // returned values must have the same low byte.
v := b[0] v := b[0]
...@@ -21,7 +21,7 @@ func read(b []byte) (uint16, uint16) { ...@@ -21,7 +21,7 @@ func read(b []byte) (uint16, uint16) {
const N = 100000 const N = 100000
func main() { func main1() {
done := make(chan struct{}) done := make(chan struct{})
b := make([]byte, 2) b := make([]byte, 2)
go func() { go func() {
...@@ -33,7 +33,7 @@ func main() { ...@@ -33,7 +33,7 @@ func main() {
}() }()
go func() { go func() {
for i := 0; i < N; i++ { for i := 0; i < N; i++ {
x, y := read(b) x, y := read1(b)
if byte(x) != byte(y) { if byte(x) != byte(y) {
fmt.Printf("x=%x y=%x\n", x, y) fmt.Printf("x=%x y=%x\n", x, y)
panic("bad") panic("bad")
...@@ -44,3 +44,40 @@ func main() { ...@@ -44,3 +44,40 @@ func main() {
<-done <-done
<-done <-done
} }
//go:noinline
func read2(b []byte) (uint16, uint16) {
// There is only a single read of b[1]. The two
// returned values must have the same high byte.
v := uint16(b[1]) << 8
return v, uint16(b[0]) | v
}
func main2() {
done := make(chan struct{})
b := make([]byte, 2)
go func() {
for i := 0; i < N; i++ {
b[0] = byte(i)
b[1] = byte(i)
}
done <- struct{}{}
}()
go func() {
for i := 0; i < N; i++ {
x, y := read2(b)
if x&0xff00 != y&0xff00 {
fmt.Printf("x=%x y=%x\n", x, y)
panic("bad")
}
}
done <- struct{}{}
}()
<-done
<-done
}
func main() {
main1()
main2()
}
...@@ -90,7 +90,7 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool) ...@@ -90,7 +90,7 @@ func applyRewrite(f *Func, rb func(*Block) bool, rv func(*Value, *Config) bool)
break break
} }
} }
// remove clobbered copies // remove clobbered values
for _, b := range f.Blocks { for _, b := range f.Blocks {
j := 0 j := 0
for i, v := range b.Values { for i, v := range b.Values {
...@@ -367,3 +367,13 @@ found: ...@@ -367,3 +367,13 @@ found:
} }
return nil // too far away return nil // too far away
} }
// clobber invalidates v. Returns true.
// clobber is used by rewrite rules to:
// A) make sure v is really dead and never used again.
// B) decrement use counts of v's args.
func clobber(v *Value) bool {
v.reset(OpInvalid)
// Note: leave v.Block intact. The Block field is used after clobber.
return true
}
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