зеркало из https://github.com/CryptoPro/go.git
cmd/gc: don't give credit for NOPs during register allocation
The register allocator decides which variables should be placed into registers by charging for each load/store and crediting for each use, and then selecting an allocation with minimal cost. NOPs will be eliminated, however, so using a variable in a NOP should not generate credit. Issue 7867 arises from attempted registerization of multi-word variables because they are used in NOPs. By not crediting for that use, they will no longer be considered for registerization. This fix could theoretically lead to better register allocation, but NOPs are rare relative to other instructions. Fixes #7867. LGTM=rsc R=rsc CC=golang-codereviews https://golang.org/cl/94810044
This commit is contained in:
Родитель
52961b902f
Коммит
1848d71445
|
@ -1097,18 +1097,20 @@ paint1(Reg *r, int bn)
|
|||
r->act.b[z] |= bb;
|
||||
p = r->f.prog;
|
||||
|
||||
if(r->use1.b[z] & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(debug['R'] > 1)
|
||||
print("%d%P\tu1 %Q $%d\n", r->f.loop,
|
||||
p, blsh(bn), change);
|
||||
}
|
||||
|
||||
if((r->use2.b[z]|r->set.b[z]) & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(debug['R'] > 1)
|
||||
print("%d%P\tu2 %Q $%d\n", r->f.loop,
|
||||
p, blsh(bn), change);
|
||||
if(r->f.prog->as != ANOP) { // don't give credit for NOPs
|
||||
if(r->use1.b[z] & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(debug['R'] > 1)
|
||||
print("%d%P\tu1 %Q $%d\n", r->f.loop,
|
||||
p, blsh(bn), change);
|
||||
}
|
||||
if((r->use2.b[z]|r->set.b[z]) & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(debug['R'] > 1)
|
||||
print("%d%P\tu2 %Q $%d\n", r->f.loop,
|
||||
p, blsh(bn), change);
|
||||
}
|
||||
}
|
||||
|
||||
if(STORE(r) & r->regdiff.b[z] & bb) {
|
||||
|
|
|
@ -942,12 +942,11 @@ paint1(Reg *r, int bn)
|
|||
for(;;) {
|
||||
r->act.b[z] |= bb;
|
||||
|
||||
if(r->use1.b[z] & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
}
|
||||
|
||||
if((r->use2.b[z]|r->set.b[z]) & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(r->f.prog->as != ANOP) { // don't give credit for NOPs
|
||||
if(r->use1.b[z] & bb)
|
||||
change += CREF * r->f.loop;
|
||||
if((r->use2.b[z]|r->set.b[z]) & bb)
|
||||
change += CREF * r->f.loop;
|
||||
}
|
||||
|
||||
if(STORE(r) & r->regdiff.b[z] & bb) {
|
||||
|
|
|
@ -909,18 +909,19 @@ paint1(Reg *r, int bn)
|
|||
r->act.b[z] |= bb;
|
||||
p = r->f.prog;
|
||||
|
||||
if(r->use1.b[z] & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(p->as == AFMOVL || p->as == AFMOVW)
|
||||
if(BtoR(bb) != D_F0)
|
||||
change = -CINF;
|
||||
}
|
||||
|
||||
if((r->use2.b[z]|r->set.b[z]) & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(p->as == AFMOVL || p->as == AFMOVW)
|
||||
if(BtoR(bb) != D_F0)
|
||||
change = -CINF;
|
||||
if(r->f.prog->as != ANOP) { // don't give credit for NOPs
|
||||
if(r->use1.b[z] & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(p->as == AFMOVL || p->as == AFMOVW)
|
||||
if(BtoR(bb) != D_F0)
|
||||
change = -CINF;
|
||||
}
|
||||
if((r->use2.b[z]|r->set.b[z]) & bb) {
|
||||
change += CREF * r->f.loop;
|
||||
if(p->as == AFMOVL || p->as == AFMOVW)
|
||||
if(BtoR(bb) != D_F0)
|
||||
change = -CINF;
|
||||
}
|
||||
}
|
||||
|
||||
if(STORE(r) & r->regdiff.b[z] & bb) {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
// runoutput
|
||||
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Issue 7867.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
const tpl = `
|
||||
func Test%d(t %s) {
|
||||
_ = t
|
||||
_ = t
|
||||
}
|
||||
`
|
||||
|
||||
func main() {
|
||||
fmt.Println("package main")
|
||||
types := []string{
|
||||
// These types always passed
|
||||
"bool", "int", "rune",
|
||||
"*int", "uintptr",
|
||||
"float32", "float64",
|
||||
"chan struct{}",
|
||||
"map[string]struct{}",
|
||||
"func()", "func(string)error",
|
||||
|
||||
// These types caused compilation failures
|
||||
"complex64", "complex128",
|
||||
"struct{}", "struct{n int}", "struct{e error}", "struct{m map[string]string}",
|
||||
"string",
|
||||
"[4]byte",
|
||||
"[]byte",
|
||||
"interface{}", "error",
|
||||
}
|
||||
for i, typ := range types {
|
||||
fmt.Printf(tpl, i, typ)
|
||||
}
|
||||
fmt.Println("func main() {}")
|
||||
}
|
Загрузка…
Ссылка в новой задаче