Commit d47fe809 authored by Russ Cox's avatar Russ Cox

cmd/internal/gc: increase registerization limits

Also clean up code a little.

Change-Id: I23b7d2b7871b31e0974f1305e54f0c18dcab05d9
Reviewed-on: https://go-review.googlesource.com/7746Reviewed-by: default avatarDave Cheney <dave@cheney.net>
Reviewed-by: default avatarRob Pike <r@golang.org>
parent fd38dbc8
...@@ -326,7 +326,7 @@ func pushback(r0 *gc.Flow) { ...@@ -326,7 +326,7 @@ func pushback(r0 *gc.Flow) {
} }
if b == nil { if b == nil {
if gc.Debug['v'] != 0 { if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
fmt.Printf("no pushback: %v\n", r0.Prog) fmt.Printf("no pushback: %v\n", r0.Prog)
if r != nil { if r != nil {
fmt.Printf("\t%v [%d]\n", r.Prog, gc.Uniqs(r) != nil) fmt.Printf("\t%v [%d]\n", r.Prog, gc.Uniqs(r) != nil)
...@@ -336,7 +336,7 @@ func pushback(r0 *gc.Flow) { ...@@ -336,7 +336,7 @@ func pushback(r0 *gc.Flow) {
return return
} }
if gc.Debug['v'] != 0 { if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
fmt.Printf("pushback\n") fmt.Printf("pushback\n")
for r := (*gc.Flow)(b); ; r = r.Link { for r := (*gc.Flow)(b); ; r = r.Link {
fmt.Printf("\t%v\n", r.Prog) fmt.Printf("\t%v\n", r.Prog)
...@@ -366,7 +366,7 @@ func pushback(r0 *gc.Flow) { ...@@ -366,7 +366,7 @@ func pushback(r0 *gc.Flow) {
p0.From = t.From p0.From = t.From
p0.To = t.To p0.To = t.To
if gc.Debug['v'] != 0 { if gc.Debug['P'] != 0 && gc.Debug['v'] != 0 {
fmt.Printf("\tafter\n") fmt.Printf("\tafter\n")
for r := (*gc.Flow)(b); ; r = r.Link { for r := (*gc.Flow)(b); ; r = r.Link {
fmt.Printf("\t%v\n", r.Prog) fmt.Printf("\t%v\n", r.Prog)
......
// Inferno utils/cc/bits.c
// http://code.google.com/p/inferno-os/source/browse/utils/cc/bits.c
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package gc
import "fmt"
/*
Bits
bor(Bits a, Bits b)
{
Bits c;
int i;
for(i=0; i<BITS; i++)
c.b[i] = a.b[i] | b.b[i];
return c;
}
Bits
band(Bits a, Bits b)
{
Bits c;
int i;
for(i=0; i<BITS; i++)
c.b[i] = a.b[i] & b.b[i];
return c;
}
Bits
bnot(Bits a)
{
Bits c;
int i;
for(i=0; i<BITS; i++)
c.b[i] = ~a.b[i];
return c;
}
*/
func bany(a *Bits) bool {
for i := 0; i < BITS; i++ {
if a.b[i] != 0 {
return true
}
}
return false
}
/*
int
beq(Bits a, Bits b)
{
int i;
for(i=0; i<BITS; i++)
if(a.b[i] != b.b[i])
return 0;
return 1;
}
*/
func bnum(a Bits) int {
var b uint64
for i := 0; i < BITS; i++ {
b = a.b[i]
if b != 0 {
return 64*i + Bitno(b)
}
}
Fatal("bad in bnum")
return 0
}
func blsh(n uint) Bits {
c := zbits
c.b[n/64] = 1 << (n % 64)
return c
}
func btest(a *Bits, n uint) bool {
return a.b[n/64]&(1<<(n%64)) != 0
}
func biset(a *Bits, n uint) {
a.b[n/64] |= 1 << (n % 64)
}
func biclr(a *Bits, n uint) {
a.b[n/64] &^= (1 << (n % 64))
}
func Bitno(b uint64) int {
for i := 0; i < 64; i++ {
if b&(1<<uint(i)) != 0 {
return i
}
}
Fatal("bad in bitno")
return 0
}
func Qconv(bits Bits, flag int) string {
var fp string
var i int
first := 1
for bany(&bits) {
i = bnum(bits)
if first != 0 {
first = 0
} else {
fp += " "
}
if var_[i].node == nil || var_[i].node.Sym == nil {
fp += fmt.Sprintf("$%d", i)
} else {
fp += fmt.Sprintf("%s(%d)", var_[i].node.Sym.Name, i)
if var_[i].offset != 0 {
fp += fmt.Sprintf("%+d", int64(var_[i].offset))
}
}
biclr(&bits, uint(i))
}
return fp
}
...@@ -351,30 +351,6 @@ const ( ...@@ -351,30 +351,6 @@ const (
Ecomplit = 1 << 11 // type in composite literal Ecomplit = 1 << 11 // type in composite literal
) )
const (
BITS = 3
NVAR = BITS * 64
)
type Bits struct {
b [BITS]uint64
}
var zbits Bits
type Var struct {
offset int64
node *Node
nextinnode *Var
width int
id int
name int8
etype int8
addr int8
}
var var_ [NVAR]Var
type Typedef struct { type Typedef struct {
Name string Name string
Etype int Etype int
......
// Derived from Inferno utils/6c/reg.c // Derived from Inferno utils/6c/gc.h
// http://code.google.com/p/inferno-os/source/browse/utils/6c/reg.c // http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
// //
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE. // THE SOFTWARE.
// "Portable" optimizations.
package gc package gc
import ( import (
...@@ -37,124 +39,6 @@ import ( ...@@ -37,124 +39,6 @@ import (
"strings" "strings"
) )
// "Portable" optimizations.
// Derived from Inferno utils/6c/gc.h
// http://code.google.com/p/inferno-os/source/browse/utils/6c/gc.h
//
// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
// Portions Copyright © 1997-1999 Vita Nuova Limited
// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
// Portions Copyright © 2004,2006 Bruce Ellis
// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
// Portions Copyright © 2009 The Go Authors. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
const (
CLOAD = 5
CREF = 5
CINF = 1000
LOOP = 3
)
type Reg struct {
set Bits // regopt variables written by this instruction.
use1 Bits // regopt variables read by prog->from.
use2 Bits // regopt variables read by prog->to.
// refahead/refbehind are the regopt variables whose current
// value may be used in the following/preceding instructions
// up to a CALL (or the value is clobbered).
refbehind Bits
refahead Bits
// calahead/calbehind are similar, but for variables in
// instructions that are reachable after hitting at least one
// CALL.
calbehind Bits
calahead Bits
regdiff Bits
act Bits
regu uint64 // register used bitmap
}
type Rgn struct {
enter *Flow
cost int16
varno int16
regno int16
}
var Z *Node
// A Reg is a wrapper around a single Prog (one instruction) that holds
// register optimization information while the optimizer runs.
// r->prog is the instruction.
var R *Reg
const (
NRGN = 600
)
// A Rgn represents a single regopt variable over a region of code
// where a register could potentially be dedicated to that variable.
// The code encompassed by a Rgn is defined by the flow graph,
// starting at enter, flood-filling forward while varno is refahead
// and backward while varno is refbehind, and following branches. A
// single variable may be represented by multiple disjoint Rgns and
// each Rgn may choose a different register for that variable.
// Registers are allocated to regions greedily in order of descending
// cost.
var zreg Reg
var region [NRGN]Rgn
var rgp *Rgn
var nregion int
var nvar int
var regbits uint64
var externs Bits
var params Bits
var consts Bits
var addrs Bits
var ivar Bits
var ovar Bits
var change int
var maxnr int32
type OptStats struct { type OptStats struct {
Ncvtreg int32 Ncvtreg int32
Nspill int32 Nspill int32
...@@ -354,6 +238,11 @@ func fixjmp(firstp *obj.Prog) { ...@@ -354,6 +238,11 @@ func fixjmp(firstp *obj.Prog) {
var flowmark int var flowmark int
// MaxFlowProg is the maximum size program (counted in instructions)
// for which the flow code will build a graph. Functions larger than this limit
// will not have flow graphs and consequently will not be optimized.
const MaxFlowProg = 50000
func Flowstart(firstp *obj.Prog, newData func() interface{}) *Graph { func Flowstart(firstp *obj.Prog, newData func() interface{}) *Graph {
// Count and mark instructions to annotate. // Count and mark instructions to annotate.
nf := 0 nf := 0
...@@ -372,8 +261,10 @@ func Flowstart(firstp *obj.Prog, newData func() interface{}) *Graph { ...@@ -372,8 +261,10 @@ func Flowstart(firstp *obj.Prog, newData func() interface{}) *Graph {
return nil return nil
} }
if nf >= 20000 { if nf >= MaxFlowProg {
// fatal("%S is too big (%d instructions)", curfn->nname->sym, nf); if Debug['v'] != 0 {
Warn("%v is too big (%d instructions)", Sconv(Curfn.Nname.Sym, 0), nf)
}
return nil return nil
} }
...@@ -678,7 +569,7 @@ func canmerge(n *Node) bool { ...@@ -678,7 +569,7 @@ func canmerge(n *Node) bool {
func mergetemp(firstp *obj.Prog) { func mergetemp(firstp *obj.Prog) {
const ( const (
debugmerge = 1 debugmerge = 0
) )
g := Flowstart(firstp, nil) g := Flowstart(firstp, nil)
......
This diff is collapsed.
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