Commit bed8129e authored by Cherry Zhang's avatar Cherry Zhang

cmd/internal/obj: remove Follow pass

The Follow pass in the assembler backend reorders and copies
instructions. This even applies to hand-written assembly code,
which in many cases don't want to be reordered. Now that the
SSA compiler does a good job for laying out instructions, the
benefit of this pass is very little:

AMD64: (old = with Follow, new = without Follow)
name                      old time/op    new time/op    delta
BinaryTree17-12              2.78s ± 1%     2.79s ± 1%  +0.44%  (p=0.000 n=20+19)
Fannkuch11-12                3.11s ± 0%     3.31s ± 1%  +6.16%  (p=0.000 n=19+19)
FmtFprintfEmpty-12          50.9ns ± 1%    51.6ns ± 3%  +1.40%  (p=0.000 n=17+20)
FmtFprintfString-12          127ns ± 0%     128ns ± 1%  +0.88%  (p=0.000 n=17+17)
FmtFprintfInt-12             122ns ± 0%     123ns ± 1%  +0.76%  (p=0.000 n=20+19)
FmtFprintfIntInt-12          185ns ± 1%     186ns ± 1%  +0.65%  (p=0.000 n=20+19)
FmtFprintfPrefixedInt-12     192ns ± 1%     202ns ± 1%  +4.99%  (p=0.000 n=20+19)
FmtFprintfFloat-12           284ns ± 0%     288ns ± 0%  +1.33%  (p=0.000 n=15+19)
FmtManyArgs-12               807ns ± 0%     804ns ± 0%  -0.44%  (p=0.000 n=16+18)
GobDecode-12                7.23ms ± 1%    7.21ms ± 1%    ~     (p=0.052 n=20+20)
GobEncode-12                6.09ms ± 1%    6.12ms ± 1%  +0.41%  (p=0.002 n=19+19)
Gzip-12                      253ms ± 1%     255ms ± 1%  +0.95%  (p=0.000 n=18+20)
Gunzip-12                   38.4ms ± 0%    38.5ms ± 0%  +0.34%  (p=0.000 n=17+17)
HTTPClientServer-12         95.4µs ± 2%    96.1µs ± 1%  +0.78%  (p=0.002 n=19+19)
JSONEncode-12               16.5ms ± 1%    16.6ms ± 1%  +1.17%  (p=0.000 n=19+19)
JSONDecode-12               54.6ms ± 1%    55.3ms ± 1%  +1.23%  (p=0.000 n=18+18)
Mandelbrot200-12            4.47ms ± 0%    4.47ms ± 0%  +0.06%  (p=0.000 n=18+18)
GoParse-12                  3.47ms ± 1%    3.47ms ± 1%    ~     (p=0.583 n=20+20)
RegexpMatchEasy0_32-12      84.8ns ± 1%    85.2ns ± 2%  +0.51%  (p=0.022 n=20+20)
RegexpMatchEasy0_1K-12       206ns ± 1%     206ns ± 1%    ~     (p=0.770 n=20+20)
RegexpMatchEasy1_32-12      82.8ns ± 1%    83.4ns ± 1%  +0.64%  (p=0.000 n=20+19)
RegexpMatchEasy1_1K-12       363ns ± 1%     361ns ± 1%  -0.48%  (p=0.007 n=20+20)
RegexpMatchMedium_32-12      126ns ± 1%     126ns ± 0%  +0.72%  (p=0.000 n=20+20)
RegexpMatchMedium_1K-12     39.1µs ± 1%    39.8µs ± 0%  +1.73%  (p=0.000 n=19+19)
RegexpMatchHard_32-12       1.97µs ± 0%    1.98µs ± 1%  +0.29%  (p=0.005 n=18+20)
RegexpMatchHard_1K-12       59.5µs ± 1%    59.8µs ± 1%  +0.36%  (p=0.000 n=18+20)
Revcomp-12                   442ms ± 1%     445ms ± 2%  +0.67%  (p=0.000 n=19+20)
Template-12                 58.0ms ± 1%    57.5ms ± 1%  -0.85%  (p=0.000 n=19+19)
TimeParse-12                 311ns ± 0%     314ns ± 0%  +0.94%  (p=0.000 n=20+18)
TimeFormat-12                350ns ± 3%     346ns ± 0%    ~     (p=0.076 n=20+19)
[Geo mean]                  55.9µs         56.4µs       +0.80%

ARM32:
name                     old time/op    new time/op    delta
BinaryTree17-4              30.4s ± 0%     30.1s ± 0%  -1.14%  (p=0.000 n=10+8)
Fannkuch11-4                13.7s ± 0%     13.6s ± 0%  -0.75%  (p=0.000 n=10+10)
FmtFprintfEmpty-4           664ns ± 1%     651ns ± 1%  -1.96%  (p=0.000 n=7+8)
FmtFprintfString-4         1.83µs ± 2%    1.77µs ± 2%  -3.21%  (p=0.000 n=10+10)
FmtFprintfInt-4            1.57µs ± 2%    1.54µs ± 2%  -2.25%  (p=0.007 n=10+10)
FmtFprintfIntInt-4         2.37µs ± 2%    2.31µs ± 1%  -2.68%  (p=0.000 n=10+10)
FmtFprintfPrefixedInt-4    2.14µs ± 2%    2.10µs ± 1%  -1.83%  (p=0.006 n=10+10)
FmtFprintfFloat-4          3.69µs ± 2%    3.74µs ± 1%  +1.60%  (p=0.000 n=10+10)
FmtManyArgs-4              9.43µs ± 1%    9.17µs ± 1%  -2.70%  (p=0.000 n=10+10)
GobDecode-4                76.3ms ± 1%    75.5ms ± 1%  -1.14%  (p=0.003 n=10+10)
GobEncode-4                70.7ms ± 2%    69.0ms ± 1%  -2.36%  (p=0.000 n=10+10)
Gzip-4                      2.64s ± 1%     2.65s ± 0%  +0.59%  (p=0.002 n=10+10)
Gunzip-4                    402ms ± 0%     398ms ± 0%  -1.11%  (p=0.000 n=10+9)
HTTPClientServer-4          458µs ± 0%     457µs ± 0%    ~     (p=0.247 n=10+10)
JSONEncode-4                171ms ± 0%     172ms ± 0%  +0.56%  (p=0.000 n=10+10)
JSONDecode-4                672ms ± 1%     668ms ± 1%    ~     (p=0.105 n=10+10)
Mandelbrot200-4            33.5ms ± 0%    33.5ms ± 0%    ~     (p=0.156 n=9+10)
GoParse-4                  33.9ms ± 0%    34.0ms ± 0%  +0.36%  (p=0.031 n=9+9)
RegexpMatchEasy0_32-4       823ns ± 1%     835ns ± 1%  +1.49%  (p=0.000 n=8+8)
RegexpMatchEasy0_1K-4      3.99µs ± 0%    4.02µs ± 1%  +0.92%  (p=0.000 n=8+10)
RegexpMatchEasy1_32-4       877ns ± 3%     904ns ± 2%  +3.07%  (p=0.012 n=10+10)
RegexpMatchEasy1_1K-4      5.99µs ± 0%    5.97µs ± 1%  -0.38%  (p=0.023 n=8+8)
RegexpMatchMedium_32-4     1.40µs ± 2%    1.40µs ± 2%    ~     (p=0.590 n=10+9)
RegexpMatchMedium_1K-4      357µs ± 0%     355µs ± 1%  -0.72%  (p=0.000 n=7+8)
RegexpMatchHard_32-4       22.3µs ± 0%    22.1µs ± 0%  -0.49%  (p=0.000 n=8+7)
RegexpMatchHard_1K-4        661µs ± 0%     658µs ± 0%  -0.42%  (p=0.000 n=8+7)
Revcomp-4                  46.3ms ± 0%    46.3ms ± 0%    ~     (p=0.393 n=10+10)
Template-4                  753ms ± 1%     750ms ± 0%    ~     (p=0.211 n=10+9)
TimeParse-4                4.28µs ± 1%    4.22µs ± 1%  -1.34%  (p=0.000 n=8+10)
TimeFormat-4               9.00µs ± 0%    9.05µs ± 0%  +0.59%  (p=0.000 n=10+10)
[Geo mean]                  538µs          535µs       -0.55%

ARM64:
name                     old time/op    new time/op    delta
BinaryTree17-8              8.39s ± 0%     8.39s ± 0%    ~     (p=0.684 n=10+10)
Fannkuch11-8                5.95s ± 0%     5.99s ± 0%  +0.63%  (p=0.000 n=10+10)
FmtFprintfEmpty-8           116ns ± 0%     116ns ± 0%    ~     (all equal)
FmtFprintfString-8          361ns ± 0%     360ns ± 0%  -0.31%  (p=0.003 n=8+6)
FmtFprintfInt-8             290ns ± 0%     290ns ± 0%    ~     (p=0.620 n=9+9)
FmtFprintfIntInt-8          476ns ± 1%     469ns ± 0%  -1.47%  (p=0.000 n=10+6)
FmtFprintfPrefixedInt-8     412ns ± 2%     417ns ± 2%  +1.39%  (p=0.006 n=9+10)
FmtFprintfFloat-8           652ns ± 1%     652ns ± 0%    ~     (p=0.161 n=10+8)
FmtManyArgs-8              1.94µs ± 0%    1.94µs ± 2%    ~     (p=0.781 n=10+10)
GobDecode-8                17.7ms ± 1%    17.7ms ± 0%    ~     (p=0.962 n=10+7)
GobEncode-8                15.6ms ± 0%    15.6ms ± 1%    ~     (p=0.063 n=10+10)
Gzip-8                      786ms ± 0%     787ms ± 0%    ~     (p=0.356 n=10+9)
Gunzip-8                    127ms ± 0%     127ms ± 0%  +0.08%  (p=0.028 n=10+9)
HTTPClientServer-8          198µs ± 6%     198µs ± 7%    ~     (p=0.796 n=10+10)
JSONEncode-8               42.5ms ± 0%    42.2ms ± 0%  -0.73%  (p=0.000 n=9+8)
JSONDecode-8                158ms ± 1%     162ms ± 0%  +2.28%  (p=0.000 n=10+9)
Mandelbrot200-8            10.1ms ± 0%    10.1ms ± 0%  -0.01%  (p=0.000 n=10+9)
GoParse-8                  8.54ms ± 1%    8.63ms ± 1%  +1.06%  (p=0.000 n=10+9)
RegexpMatchEasy0_32-8       231ns ± 1%     225ns ± 0%  -2.52%  (p=0.000 n=9+10)
RegexpMatchEasy0_1K-8      1.63µs ± 0%    1.63µs ± 0%    ~     (p=0.170 n=10+10)
RegexpMatchEasy1_32-8       253ns ± 0%     249ns ± 0%  -1.41%  (p=0.000 n=9+10)
RegexpMatchEasy1_1K-8      2.08µs ± 0%    2.08µs ± 0%  -0.32%  (p=0.000 n=9+10)
RegexpMatchMedium_32-8      355ns ± 1%     351ns ± 0%  -1.04%  (p=0.007 n=10+7)
RegexpMatchMedium_1K-8      104µs ± 0%     104µs ± 0%    ~     (p=0.148 n=10+10)
RegexpMatchHard_32-8       5.79µs ± 0%    5.79µs ± 0%    ~     (p=0.578 n=10+10)
RegexpMatchHard_1K-8        176µs ± 0%     176µs ± 0%    ~     (p=0.137 n=10+10)
Revcomp-8                   1.37s ± 1%     1.36s ± 1%  -0.26%  (p=0.023 n=10+10)
Template-8                  151ms ± 1%     154ms ± 1%  +2.14%  (p=0.000 n=9+10)
TimeParse-8                 723ns ± 2%     721ns ± 1%    ~     (p=0.592 n=10+10)
TimeFormat-8                804ns ± 2%     798ns ± 3%    ~     (p=0.344 n=10+10)
[Geo mean]                  154µs          154µs       -0.02%

Therefore remove this pass. Also reduce text size by 0.5~2%.

Comment out some dead code in runtime/sys_nacl_amd64p32.s
which contains undefined symbols.

Change-Id: I1473986fe5b18b3d2554ce96cdc6f0999b8d955d
Reviewed-on: https://go-review.googlesource.com/36205
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 76d42744
...@@ -34,7 +34,6 @@ import ( ...@@ -34,7 +34,6 @@ import (
"cmd/internal/obj" "cmd/internal/obj"
"cmd/internal/sys" "cmd/internal/sys"
"fmt" "fmt"
"log"
"math" "math"
) )
...@@ -862,183 +861,6 @@ func initdiv(ctxt *obj.Link) { ...@@ -862,183 +861,6 @@ func initdiv(ctxt *obj.Link) {
ctxt.Sym_modu = obj.Linklookup(ctxt, "_modu", 0) ctxt.Sym_modu = obj.Linklookup(ctxt, "_modu", 0)
} }
func follow(ctxt *obj.Link, s *obj.LSym) {
ctxt.Cursym = s
firstp := ctxt.NewProg()
lastp := firstp
xfol(ctxt, s.Text, &lastp)
lastp.Link = nil
s.Text = firstp.Link
}
func relinv(a obj.As) obj.As {
switch a {
case ABEQ:
return ABNE
case ABNE:
return ABEQ
case ABCS:
return ABCC
case ABHS:
return ABLO
case ABCC:
return ABCS
case ABLO:
return ABHS
case ABMI:
return ABPL
case ABPL:
return ABMI
case ABVS:
return ABVC
case ABVC:
return ABVS
case ABHI:
return ABLS
case ABLS:
return ABHI
case ABGE:
return ABLT
case ABLT:
return ABGE
case ABGT:
return ABLE
case ABLE:
return ABGT
}
log.Fatalf("unknown relation: %s", Anames[a])
return 0
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var r *obj.Prog
var i int
loop:
if p == nil {
return
}
a := p.As
if a == AB {
q = p.Pcond
if q != nil && q.As != obj.ATEXT {
p.Mark |= FOLL
p = q
if p.Mark&FOLL == 0 {
goto loop
}
}
}
if p.Mark&FOLL != 0 {
i = 0
q = p
for ; i < 4; i, q = i+1, q.Link {
if q == *last || q == nil {
break
}
a = q.As
if a == obj.ANOP {
i--
continue
}
if a == AB || (a == obj.ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == obj.AUNDEF {
goto copy
}
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
continue
}
if a != ABEQ && a != ABNE {
continue
}
copy:
for {
r = ctxt.NewProg()
*r = *p
if r.Mark&FOLL == 0 {
fmt.Printf("can't happen 1\n")
}
r.Mark |= FOLL
if p != q {
p = p.Link
(*last).Link = r
*last = r
continue
}
(*last).Link = r
*last = r
if a == AB || (a == obj.ARET && q.Scond == C_SCOND_NONE) || a == ARFE || a == obj.AUNDEF {
return
}
r.As = ABNE
if a == ABNE {
r.As = ABEQ
}
r.Pcond = p.Link
r.Link = p.Pcond
if r.Link.Mark&FOLL == 0 {
xfol(ctxt, r.Link, last)
}
if r.Pcond.Mark&FOLL == 0 {
fmt.Printf("can't happen 2\n")
}
return
}
}
a = AB
q = ctxt.NewProg()
q.As = a
q.Pos = p.Pos
q.To.Type = obj.TYPE_BRANCH
q.To.Offset = p.Pc
q.Pcond = p
p = q
}
p.Mark |= FOLL
(*last).Link = p
*last = p
if a == AB || (a == obj.ARET && p.Scond == C_SCOND_NONE) || a == ARFE || a == obj.AUNDEF {
return
}
if p.Pcond != nil {
if a != ABL && a != ABX && p.Link != nil {
q = obj.Brchain(ctxt, p.Link)
if a != obj.ATEXT {
if q != nil && (q.Mark&FOLL != 0) {
p.As = relinv(a)
p.Link = p.Pcond
p.Pcond = q
}
}
xfol(ctxt, p.Link, last)
q = obj.Brchain(ctxt, p.Pcond)
if q == nil {
q = p.Pcond
}
if q.Mark&FOLL != 0 {
p.Pcond = q
return
}
p = q
goto loop
}
}
p = p.Link
goto loop
}
var unaryDst = map[obj.As]bool{ var unaryDst = map[obj.As]bool{
ASWI: true, ASWI: true,
AWORD: true, AWORD: true,
...@@ -1048,7 +870,6 @@ var Linkarm = obj.LinkArch{ ...@@ -1048,7 +870,6 @@ var Linkarm = obj.LinkArch{
Arch: sys.ArchARM, Arch: sys.ArchARM,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span5, Assemble: span5,
Follow: follow,
Progedit: progedit, Progedit: progedit,
UnaryDst: unaryDst, UnaryDst: unaryDst,
} }
...@@ -34,7 +34,6 @@ import ( ...@@ -34,7 +34,6 @@ import (
"cmd/internal/obj" "cmd/internal/obj"
"cmd/internal/sys" "cmd/internal/sys"
"fmt" "fmt"
"log"
"math" "math"
) )
...@@ -443,191 +442,6 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) { ...@@ -443,191 +442,6 @@ func rewriteToUseGot(ctxt *obj.Link, p *obj.Prog) {
obj.Nopout(p) obj.Nopout(p)
} }
func follow(ctxt *obj.Link, s *obj.LSym) {
ctxt.Cursym = s
firstp := ctxt.NewProg()
lastp := firstp
xfol(ctxt, s.Text, &lastp)
lastp.Link = nil
s.Text = firstp.Link
}
func relinv(a obj.As) obj.As {
switch a {
case ABEQ:
return ABNE
case ABNE:
return ABEQ
case ABCS:
return ABCC
case ABHS:
return ABLO
case ABCC:
return ABCS
case ABLO:
return ABHS
case ABMI:
return ABPL
case ABPL:
return ABMI
case ABVS:
return ABVC
case ABVC:
return ABVS
case ABHI:
return ABLS
case ABLS:
return ABHI
case ABGE:
return ABLT
case ABLT:
return ABGE
case ABGT:
return ABLE
case ABLE:
return ABGT
case ACBZ:
return ACBNZ
case ACBNZ:
return ACBZ
case ACBZW:
return ACBNZW
case ACBNZW:
return ACBZW
}
log.Fatalf("unknown relation: %s", Anames[a-obj.ABaseARM64])
return 0
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var r *obj.Prog
var i int
loop:
if p == nil {
return
}
a := p.As
if a == AB {
q = p.Pcond
if q != nil {
p.Mark |= FOLL
p = q
if !(p.Mark&FOLL != 0) {
goto loop
}
}
}
if p.Mark&FOLL != 0 {
i = 0
q = p
for ; i < 4; i, q = i+1, q.Link {
if q == *last || q == nil {
break
}
a = q.As
if a == obj.ANOP {
i--
continue
}
if a == AB || a == obj.ARET || a == AERET {
goto copy
}
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
continue
}
if a != ABEQ && a != ABNE {
continue
}
copy:
for {
r = ctxt.NewProg()
*r = *p
if !(r.Mark&FOLL != 0) {
fmt.Printf("can't happen 1\n")
}
r.Mark |= FOLL
if p != q {
p = p.Link
(*last).Link = r
*last = r
continue
}
(*last).Link = r
*last = r
if a == AB || a == obj.ARET || a == AERET {
return
}
if a == ABNE {
r.As = ABEQ
} else {
r.As = ABNE
}
r.Pcond = p.Link
r.Link = p.Pcond
if !(r.Link.Mark&FOLL != 0) {
xfol(ctxt, r.Link, last)
}
if !(r.Pcond.Mark&FOLL != 0) {
fmt.Printf("can't happen 2\n")
}
return
}
}
a = AB
q = ctxt.NewProg()
q.As = a
q.Pos = p.Pos
q.To.Type = obj.TYPE_BRANCH
q.To.Offset = p.Pc
q.Pcond = p
p = q
}
p.Mark |= FOLL
(*last).Link = p
*last = p
if a == AB || a == obj.ARET || a == AERET {
return
}
if p.Pcond != nil {
if a != ABL && p.Link != nil {
q = obj.Brchain(ctxt, p.Link)
if a != obj.ATEXT {
if q != nil && (q.Mark&FOLL != 0) {
p.As = relinv(a)
p.Link = p.Pcond
p.Pcond = q
}
}
xfol(ctxt, p.Link, last)
q = obj.Brchain(ctxt, p.Pcond)
if q == nil {
q = p.Pcond
}
if q.Mark&FOLL != 0 {
p.Pcond = q
return
}
p = q
goto loop
}
}
p = p.Link
goto loop
}
func preprocess(ctxt *obj.Link, cursym *obj.LSym) { func preprocess(ctxt *obj.Link, cursym *obj.LSym) {
ctxt.Cursym = cursym ctxt.Cursym = cursym
...@@ -998,7 +812,6 @@ var Linkarm64 = obj.LinkArch{ ...@@ -998,7 +812,6 @@ var Linkarm64 = obj.LinkArch{
Arch: sys.ArchARM64, Arch: sys.ArchARM64,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span7, Assemble: span7,
Follow: follow,
Progedit: progedit, Progedit: progedit,
UnaryDst: unaryDst, UnaryDst: unaryDst,
} }
...@@ -804,7 +804,6 @@ type LinkArch struct { ...@@ -804,7 +804,6 @@ type LinkArch struct {
*sys.Arch *sys.Arch
Preprocess func(*Link, *LSym) Preprocess func(*Link, *LSym)
Assemble func(*Link, *LSym) Assemble func(*Link, *LSym)
Follow func(*Link, *LSym)
Progedit func(*Link, *Prog) Progedit func(*Link, *Prog)
UnaryDst map[As]bool // Instruction takes one operand, a destination. UnaryDst map[As]bool // Instruction takes one operand, a destination.
} }
......
...@@ -1418,151 +1418,10 @@ func compound(ctxt *obj.Link, p *obj.Prog) bool { ...@@ -1418,151 +1418,10 @@ func compound(ctxt *obj.Link, p *obj.Prog) bool {
return false return false
} }
func follow(ctxt *obj.Link, s *obj.LSym) {
ctxt.Cursym = s
firstp := ctxt.NewProg()
lastp := firstp
xfol(ctxt, s.Text, &lastp)
lastp.Link = nil
s.Text = firstp.Link
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var r *obj.Prog
var i int
loop:
if p == nil {
return
}
a := p.As
if a == AJMP {
q = p.Pcond
if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
p.Mark |= FOLL
(*last).Link = p
*last = p
p = p.Link
xfol(ctxt, p, last)
p = q
if p != nil && p.Mark&FOLL == 0 {
goto loop
}
return
}
if q != nil {
p.Mark |= FOLL
p = q
if p.Mark&FOLL == 0 {
goto loop
}
}
}
if p.Mark&FOLL != 0 {
i = 0
q = p
for ; i < 4; i, q = i+1, q.Link {
if q == *last || (q.Mark&NOSCHED != 0) {
break
}
a = q.As
if a == obj.ANOP {
i--
continue
}
if a == AJMP || a == ARET || a == ARFE {
goto copy
}
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
continue
}
if a != ABEQ && a != ABNE {
continue
}
copy:
for {
r = ctxt.NewProg()
*r = *p
if r.Mark&FOLL == 0 {
fmt.Printf("can't happen 1\n")
}
r.Mark |= FOLL
if p != q {
p = p.Link
(*last).Link = r
*last = r
continue
}
(*last).Link = r
*last = r
if a == AJMP || a == ARET || a == ARFE {
return
}
r.As = ABNE
if a == ABNE {
r.As = ABEQ
}
r.Pcond = p.Link
r.Link = p.Pcond
if r.Link.Mark&FOLL == 0 {
xfol(ctxt, r.Link, last)
}
if r.Pcond.Mark&FOLL == 0 {
fmt.Printf("can't happen 2\n")
}
return
}
}
a = AJMP
q = ctxt.NewProg()
q.As = a
q.Pos = p.Pos
q.To.Type = obj.TYPE_BRANCH
q.To.Offset = p.Pc
q.Pcond = p
p = q
}
p.Mark |= FOLL
(*last).Link = p
*last = p
if a == AJMP || a == ARET || a == ARFE {
if p.Mark&NOSCHED != 0 {
p = p.Link
goto loop
}
return
}
if p.Pcond != nil {
if a != AJAL && p.Link != nil {
xfol(ctxt, p.Link, last)
p = p.Pcond
if p == nil || (p.Mark&FOLL != 0) {
return
}
goto loop
}
}
p = p.Link
goto loop
}
var Linkmips64 = obj.LinkArch{ var Linkmips64 = obj.LinkArch{
Arch: sys.ArchMIPS64, Arch: sys.ArchMIPS64,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span0, Assemble: span0,
Follow: follow,
Progedit: progedit, Progedit: progedit,
} }
...@@ -1570,7 +1429,6 @@ var Linkmips64le = obj.LinkArch{ ...@@ -1570,7 +1429,6 @@ var Linkmips64le = obj.LinkArch{
Arch: sys.ArchMIPS64LE, Arch: sys.ArchMIPS64LE,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span0, Assemble: span0,
Follow: follow,
Progedit: progedit, Progedit: progedit,
} }
...@@ -1578,7 +1436,6 @@ var Linkmips = obj.LinkArch{ ...@@ -1578,7 +1436,6 @@ var Linkmips = obj.LinkArch{
Arch: sys.ArchMIPS, Arch: sys.ArchMIPS,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span0, Assemble: span0,
Follow: follow,
Progedit: progedit, Progedit: progedit,
} }
...@@ -1586,6 +1443,5 @@ var Linkmipsle = obj.LinkArch{ ...@@ -1586,6 +1443,5 @@ var Linkmipsle = obj.LinkArch{
Arch: sys.ArchMIPSLE, Arch: sys.ArchMIPSLE,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span0, Assemble: span0,
Follow: follow,
Progedit: progedit, Progedit: progedit,
} }
...@@ -159,9 +159,6 @@ func flushplist(ctxt *Link, freeProgs bool) { ...@@ -159,9 +159,6 @@ func flushplist(ctxt *Link, freeProgs bool) {
for _, s := range text { for _, s := range text {
mkfwd(s) mkfwd(s)
linkpatch(ctxt, s) linkpatch(ctxt, s)
if ctxt.Flag_optimize {
ctxt.Arch.Follow(ctxt, s)
}
ctxt.Arch.Preprocess(ctxt, s) ctxt.Arch.Preprocess(ctxt, s)
ctxt.Arch.Assemble(ctxt, s) ctxt.Arch.Assemble(ctxt, s)
fieldtrack(ctxt, s) fieldtrack(ctxt, s)
......
...@@ -1067,177 +1067,10 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog { ...@@ -1067,177 +1067,10 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32) *obj.Prog {
return p return p
} }
func follow(ctxt *obj.Link, s *obj.LSym) {
ctxt.Cursym = s
firstp := ctxt.NewProg()
lastp := firstp
xfol(ctxt, s.Text, &lastp)
lastp.Link = nil
s.Text = firstp.Link
}
func relinv(a obj.As) obj.As {
switch a {
case ABEQ:
return ABNE
case ABNE:
return ABEQ
case ABGE:
return ABLT
case ABLT:
return ABGE
case ABGT:
return ABLE
case ABLE:
return ABGT
case ABVC:
return ABVS
case ABVS:
return ABVC
}
return 0
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var r *obj.Prog
var b obj.As
var i int
loop:
if p == nil {
return
}
a := p.As
if a == ABR {
q = p.Pcond
if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
p.Mark |= FOLL
(*last).Link = p
*last = p
p = p.Link
xfol(ctxt, p, last)
p = q
if p != nil && p.Mark&FOLL == 0 {
goto loop
}
return
}
if q != nil {
p.Mark |= FOLL
p = q
if p.Mark&FOLL == 0 {
goto loop
}
}
}
if p.Mark&FOLL != 0 {
i = 0
q = p
for ; i < 4; i, q = i+1, q.Link {
if q == *last || (q.Mark&NOSCHED != 0) {
break
}
b = 0 /* set */
a = q.As
if a == obj.ANOP {
i--
continue
}
if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
goto copy
}
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
continue
}
b = relinv(a)
if b == 0 {
continue
}
copy:
for {
r = ctxt.NewProg()
*r = *p
if r.Mark&FOLL == 0 {
fmt.Printf("can't happen 1\n")
}
r.Mark |= FOLL
if p != q {
p = p.Link
(*last).Link = r
*last = r
continue
}
(*last).Link = r
*last = r
if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
return
}
r.As = b
r.Pcond = p.Link
r.Link = p.Pcond
if r.Link.Mark&FOLL == 0 {
xfol(ctxt, r.Link, last)
}
if r.Pcond.Mark&FOLL == 0 {
fmt.Printf("can't happen 2\n")
}
return
}
}
a = ABR
q = ctxt.NewProg()
q.As = a
q.Pos = p.Pos
q.To.Type = obj.TYPE_BRANCH
q.To.Offset = p.Pc
q.Pcond = p
p = q
}
p.Mark |= FOLL
(*last).Link = p
*last = p
if a == ABR || a == obj.ARET || a == ARFI || a == ARFCI || a == ARFID || a == AHRFID {
if p.Mark&NOSCHED != 0 {
p = p.Link
goto loop
}
return
}
if p.Pcond != nil {
if a != ABL && p.Link != nil {
xfol(ctxt, p.Link, last)
p = p.Pcond
if p == nil || (p.Mark&FOLL != 0) {
return
}
goto loop
}
}
p = p.Link
goto loop
}
var Linkppc64 = obj.LinkArch{ var Linkppc64 = obj.LinkArch{
Arch: sys.ArchPPC64, Arch: sys.ArchPPC64,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span9, Assemble: span9,
Follow: follow,
Progedit: progedit, Progedit: progedit,
} }
...@@ -1245,6 +1078,5 @@ var Linkppc64le = obj.LinkArch{ ...@@ -1245,6 +1078,5 @@ var Linkppc64le = obj.LinkArch{
Arch: sys.ArchPPC64LE, Arch: sys.ArchPPC64LE,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span9, Assemble: span9,
Follow: follow,
Progedit: progedit, Progedit: progedit,
} }
...@@ -837,176 +837,6 @@ func stacksplitPost(ctxt *obj.Link, p *obj.Prog, pPre *obj.Prog, pPreempt *obj.P ...@@ -837,176 +837,6 @@ func stacksplitPost(ctxt *obj.Link, p *obj.Prog, pPre *obj.Prog, pPreempt *obj.P
return p return p
} }
var pc_cnt int64
func follow(ctxt *obj.Link, s *obj.LSym) {
ctxt.Cursym = s
pc_cnt = 0
firstp := ctxt.NewProg()
lastp := firstp
xfol(ctxt, s.Text, &lastp)
lastp.Link = nil
s.Text = firstp.Link
}
func relinv(a obj.As) obj.As {
switch a {
case ABEQ:
return ABNE
case ABNE:
return ABEQ
case ABGE:
return ABLT
case ABLT:
return ABGE
case ABGT:
return ABLE
case ABLE:
return ABGT
case ABVC:
return ABVS
case ABVS:
return ABVC
}
return 0
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var r *obj.Prog
var b obj.As
for p != nil {
a := p.As
if a == ABR {
q = p.Pcond
if (p.Mark&NOSCHED != 0) || q != nil && (q.Mark&NOSCHED != 0) {
p.Mark |= FOLL
(*last).Link = p
*last = p
(*last).Pc = pc_cnt
pc_cnt += 1
p = p.Link
xfol(ctxt, p, last)
p = q
if p != nil && p.Mark&FOLL == 0 {
continue
}
return
}
if q != nil {
p.Mark |= FOLL
p = q
if p.Mark&FOLL == 0 {
continue
}
}
}
if p.Mark&FOLL != 0 {
q = p
for i := 0; i < 4; i, q = i+1, q.Link {
if q == *last || (q.Mark&NOSCHED != 0) {
break
}
b = 0 /* set */
a = q.As
if a == obj.ANOP {
i--
continue
}
if a != ABR && a != obj.ARET {
if q.Pcond == nil || (q.Pcond.Mark&FOLL != 0) {
continue
}
b = relinv(a)
if b == 0 {
continue
}
}
for {
r = ctxt.NewProg()
*r = *p
if r.Mark&FOLL == 0 {
fmt.Printf("can't happen 1\n")
}
r.Mark |= FOLL
if p != q {
p = p.Link
(*last).Link = r
*last = r
(*last).Pc = pc_cnt
pc_cnt += 1
continue
}
(*last).Link = r
*last = r
(*last).Pc = pc_cnt
pc_cnt += 1
if a == ABR || a == obj.ARET {
return
}
r.As = b
r.Pcond = p.Link
r.Link = p.Pcond
if r.Link.Mark&FOLL == 0 {
xfol(ctxt, r.Link, last)
}
if r.Pcond.Mark&FOLL == 0 {
fmt.Printf("can't happen 2\n")
}
return
}
}
a = ABR
q = ctxt.NewProg()
q.As = a
q.Pos = p.Pos
q.To.Type = obj.TYPE_BRANCH
q.To.Offset = p.Pc
q.Pcond = p
p = q
}
p.Mark |= FOLL
(*last).Link = p
*last = p
(*last).Pc = pc_cnt
pc_cnt += 1
if a == ABR || a == obj.ARET {
if p.Mark&NOSCHED != 0 {
p = p.Link
continue
}
return
}
if p.Pcond != nil {
if a != ABL && p.Link != nil {
xfol(ctxt, p.Link, last)
p = p.Pcond
if p == nil || (p.Mark&FOLL != 0) {
return
}
continue
}
}
p = p.Link
}
}
var unaryDst = map[obj.As]bool{ var unaryDst = map[obj.As]bool{
ASTCK: true, ASTCK: true,
ASTCKC: true, ASTCKC: true,
...@@ -1022,7 +852,6 @@ var Links390x = obj.LinkArch{ ...@@ -1022,7 +852,6 @@ var Links390x = obj.LinkArch{
Arch: sys.ArchS390X, Arch: sys.ArchS390X,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: spanz, Assemble: spanz,
Follow: follow,
Progedit: progedit, Progedit: progedit,
UnaryDst: unaryDst, UnaryDst: unaryDst,
} }
...@@ -34,7 +34,6 @@ import ( ...@@ -34,7 +34,6 @@ import (
"cmd/internal/obj" "cmd/internal/obj"
"cmd/internal/sys" "cmd/internal/sys"
"fmt" "fmt"
"log"
"math" "math"
"strings" "strings"
) )
...@@ -1183,241 +1182,6 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32) *ob ...@@ -1183,241 +1182,6 @@ func stacksplit(ctxt *obj.Link, p *obj.Prog, framesize int32, textarg int32) *ob
return jls return jls
} }
func follow(ctxt *obj.Link, s *obj.LSym) {
ctxt.Cursym = s
firstp := ctxt.NewProg()
lastp := firstp
xfol(ctxt, s.Text, &lastp)
lastp.Link = nil
s.Text = firstp.Link
}
func nofollow(a obj.As) bool {
switch a {
case obj.AJMP,
obj.ARET,
AIRETL,
AIRETQ,
AIRETW,
ARETFL,
ARETFQ,
ARETFW,
obj.AUNDEF:
return true
}
return false
}
func pushpop(a obj.As) bool {
switch a {
case APUSHL,
APUSHFL,
APUSHQ,
APUSHFQ,
APUSHW,
APUSHFW,
APOPL,
APOPFL,
APOPQ,
APOPFQ,
APOPW,
APOPFW:
return true
}
return false
}
func relinv(a obj.As) obj.As {
switch a {
case AJEQ:
return AJNE
case AJNE:
return AJEQ
case AJLE:
return AJGT
case AJLS:
return AJHI
case AJLT:
return AJGE
case AJMI:
return AJPL
case AJGE:
return AJLT
case AJPL:
return AJMI
case AJGT:
return AJLE
case AJHI:
return AJLS
case AJCS:
return AJCC
case AJCC:
return AJCS
case AJPS:
return AJPC
case AJPC:
return AJPS
case AJOS:
return AJOC
case AJOC:
return AJOS
}
log.Fatalf("unknown relation: %s", a)
return 0
}
func xfol(ctxt *obj.Link, p *obj.Prog, last **obj.Prog) {
var q *obj.Prog
var i int
var a obj.As
loop:
if p == nil {
return
}
if p.As == obj.AJMP {
q = p.Pcond
if q != nil && q.As != obj.ATEXT {
/* mark instruction as done and continue layout at target of jump */
p.Mark |= DONE
p = q
if p.Mark&DONE == 0 {
goto loop
}
}
}
if p.Mark&DONE != 0 {
/*
* p goes here, but already used it elsewhere.
* copy up to 4 instructions or else branch to other copy.
*/
i = 0
q = p
for ; i < 4; i, q = i+1, q.Link {
if q == nil {
break
}
if q == *last {
break
}
a = q.As
if a == obj.ANOP {
i--
continue
}
if nofollow(a) || pushpop(a) {
break // NOTE(rsc): arm does goto copy
}
if q.Pcond == nil || q.Pcond.Mark&DONE != 0 {
continue
}
if a == obj.ACALL || a == ALOOP {
continue
}
for {
if p.As == obj.ANOP {
p = p.Link
continue
}
q = obj.Copyp(ctxt, p)
p = p.Link
q.Mark |= DONE
(*last).Link = q
*last = q
if q.As != a || q.Pcond == nil || q.Pcond.Mark&DONE != 0 {
continue
}
q.As = relinv(q.As)
p = q.Pcond
q.Pcond = q.Link
q.Link = p
xfol(ctxt, q.Link, last)
p = q.Link
if p.Mark&DONE != 0 {
return
}
goto loop
/* */
}
}
q = ctxt.NewProg()
q.As = obj.AJMP
q.Pos = p.Pos
q.To.Type = obj.TYPE_BRANCH
q.To.Offset = p.Pc
q.Pcond = p
p = q
}
/* emit p */
p.Mark |= DONE
(*last).Link = p
*last = p
a = p.As
/* continue loop with what comes after p */
if nofollow(a) {
return
}
if p.Pcond != nil && a != obj.ACALL {
/*
* some kind of conditional branch.
* recurse to follow one path.
* continue loop on the other.
*/
q = obj.Brchain(ctxt, p.Pcond)
if q != nil {
p.Pcond = q
}
q = obj.Brchain(ctxt, p.Link)
if q != nil {
p.Link = q
}
if p.From.Type == obj.TYPE_CONST {
if p.From.Offset == 1 {
/*
* expect conditional jump to be taken.
* rewrite so that's the fall-through case.
*/
p.As = relinv(a)
q = p.Link
p.Link = p.Pcond
p.Pcond = q
}
} else {
q = p.Link
if q.Mark&DONE != 0 {
if a != ALOOP {
p.As = relinv(a)
p.Link = p.Pcond
p.Pcond = q
}
}
}
xfol(ctxt, p.Link, last)
if p.Pcond.Mark&DONE != 0 {
return
}
p = p.Pcond
goto loop
}
p = p.Link
goto loop
}
var unaryDst = map[obj.As]bool{ var unaryDst = map[obj.As]bool{
ABSWAPL: true, ABSWAPL: true,
ABSWAPQ: true, ABSWAPQ: true,
...@@ -1472,7 +1236,6 @@ var Linkamd64 = obj.LinkArch{ ...@@ -1472,7 +1236,6 @@ var Linkamd64 = obj.LinkArch{
Arch: sys.ArchAMD64, Arch: sys.ArchAMD64,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span6, Assemble: span6,
Follow: follow,
Progedit: progedit, Progedit: progedit,
UnaryDst: unaryDst, UnaryDst: unaryDst,
} }
...@@ -1481,7 +1244,6 @@ var Linkamd64p32 = obj.LinkArch{ ...@@ -1481,7 +1244,6 @@ var Linkamd64p32 = obj.LinkArch{
Arch: sys.ArchAMD64P32, Arch: sys.ArchAMD64P32,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span6, Assemble: span6,
Follow: follow,
Progedit: progedit, Progedit: progedit,
UnaryDst: unaryDst, UnaryDst: unaryDst,
} }
...@@ -1490,7 +1252,6 @@ var Link386 = obj.LinkArch{ ...@@ -1490,7 +1252,6 @@ var Link386 = obj.LinkArch{
Arch: sys.Arch386, Arch: sys.Arch386,
Preprocess: preprocess, Preprocess: preprocess,
Assemble: span6, Assemble: span6,
Follow: follow,
Progedit: progedit, Progedit: progedit,
UnaryDst: unaryDst, UnaryDst: unaryDst,
} }
...@@ -366,40 +366,40 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80 ...@@ -366,40 +366,40 @@ TEXT runtime·sigtramp(SB),NOSPLIT,$80
// 136(SI) is saved EFLAGS, never to be seen again // 136(SI) is saved EFLAGS, never to be seen again
JMP SI JMP SI
debughandler: //debughandler:
// print basic information //// print basic information
LEAL ctxt+0(FP), DI //LEAL ctxt+0(FP), DI
MOVL $runtime·sigtrampf(SB), AX //MOVL $runtime·sigtrampf(SB), AX
MOVL AX, 0(SP) //MOVL AX, 0(SP)
MOVQ (16*4+16*8)(DI), BX // rip //MOVQ (16*4+16*8)(DI), BX // rip
MOVQ BX, 8(SP) //MOVQ BX, 8(SP)
MOVQ (16*4+0*8)(DI), BX // rax //MOVQ (16*4+0*8)(DI), BX // rax
MOVQ BX, 16(SP) //MOVQ BX, 16(SP)
MOVQ (16*4+1*8)(DI), BX // rcx //MOVQ (16*4+1*8)(DI), BX // rcx
MOVQ BX, 24(SP) //MOVQ BX, 24(SP)
MOVQ (16*4+2*8)(DI), BX // rdx //MOVQ (16*4+2*8)(DI), BX // rdx
MOVQ BX, 32(SP) //MOVQ BX, 32(SP)
MOVQ (16*4+3*8)(DI), BX // rbx //MOVQ (16*4+3*8)(DI), BX // rbx
MOVQ BX, 40(SP) //MOVQ BX, 40(SP)
MOVQ (16*4+7*8)(DI), BX // rdi //MOVQ (16*4+7*8)(DI), BX // rdi
MOVQ BX, 48(SP) //MOVQ BX, 48(SP)
MOVQ (16*4+15*8)(DI), BX // r15 //MOVQ (16*4+15*8)(DI), BX // r15
MOVQ BX, 56(SP) //MOVQ BX, 56(SP)
MOVQ (16*4+4*8)(DI), BX // rsp //MOVQ (16*4+4*8)(DI), BX // rsp
MOVQ 0(BX), BX //MOVQ 0(BX), BX
MOVQ BX, 64(SP) //MOVQ BX, 64(SP)
CALL runtime·printf(SB) //CALL runtime·printf(SB)
//
LEAL ctxt+0(FP), DI //LEAL ctxt+0(FP), DI
MOVQ (16*4+16*8)(DI), BX // rip //MOVQ (16*4+16*8)(DI), BX // rip
MOVL BX, 0(SP) //MOVL BX, 0(SP)
MOVQ (16*4+4*8)(DI), BX // rsp //MOVQ (16*4+4*8)(DI), BX // rsp
MOVL BX, 4(SP) //MOVL BX, 4(SP)
MOVL $0, 8(SP) // lr //MOVL $0, 8(SP) // lr
get_tls(CX) //get_tls(CX)
MOVL g(CX), BX //MOVL g(CX), BX
MOVL BX, 12(SP) // gp //MOVL BX, 12(SP) // gp
CALL runtime·traceback(SB) //CALL runtime·traceback(SB)
notls: notls:
MOVL 0, AX MOVL 0, AX
......
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