Commit 4a7e5bca authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/internal/gc: clean up bgen

This cleanup is in anticipation of implementing
jump-free booleans (CL 2284) and zero-aware
comparisons (issue 10381).

No functional changes. Passes toolstash -cmp.

Change-Id: I50f394c60fa2927e177d7fc85b75085060a9e912
Reviewed-on: https://go-review.googlesource.com/8738Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 6a2b0c0b
......@@ -738,91 +738,37 @@ abop: // asymmetric binary
return
}
func bgen_float(n *gc.Node, true_ int, likely int, to *obj.Prog) {
func bgen_float(n *gc.Node, wantTrue bool, likely int, to *obj.Prog) {
nl := n.Left
nr := n.Right
a := int(n.Op)
if true_ == 0 {
if !wantTrue {
// brcom is not valid on floats when NaN is involved.
p1 := gc.Gbranch(obj.AJMP, nil, 0)
p2 := gc.Gbranch(obj.AJMP, nil, 0)
gc.Patch(p1, gc.Pc)
// No need to avoid re-genning ninit.
bgen_float(n, 1, -likely, p2)
bgen_float(n, true, -likely, p2)
gc.Patch(gc.Gbranch(obj.AJMP, nil, 0), to)
gc.Patch(p2, gc.Pc)
return
}
var tmp gc.Node
var et int
var n2 gc.Node
var ax gc.Node
if !gc.Thearch.Use387 {
if !nl.Addable {
var n1 gc.Node
gc.Tempname(&n1, nl.Type)
gc.Cgen(nl, &n1)
nl = &n1
}
if !nr.Addable {
var tmp gc.Node
gc.Tempname(&tmp, nr.Type)
gc.Cgen(nr, &tmp)
nr = &tmp
}
var n2 gc.Node
gc.Regalloc(&n2, nr.Type, nil)
gmove(nr, &n2)
nr = &n2
if nl.Op != gc.OREGISTER {
var n3 gc.Node
gc.Regalloc(&n3, nl.Type, nil)
gmove(nl, &n3)
nl = &n3
}
if a == gc.OGE || a == gc.OGT {
// only < and <= work right with NaN; reverse if needed
r := nr
nr = nl
nl = r
a = gc.Brrev(a)
}
gins(foptoas(gc.OCMP, nr.Type, 0), nl, nr)
if nl.Op == gc.OREGISTER {
gc.Regfree(nl)
}
gc.Regfree(nr)
goto ret
} else {
goto x87
}
x87:
if gc.Thearch.Use387 {
a = gc.Brrev(a) // because the args are stacked
if a == gc.OGE || a == gc.OGT {
// only < and <= work right with NaN; reverse if needed
r := nr
nr = nl
nl = r
nl, nr = nr, nl
a = gc.Brrev(a)
}
var ax, n2, tmp gc.Node
gc.Nodreg(&tmp, nr.Type, x86.REG_F0)
gc.Nodreg(&n2, nr.Type, x86.REG_F0+1)
gc.Nodreg(&ax, gc.Types[gc.TUINT16], x86.REG_AX)
et = gc.Simsimtype(nr.Type)
if et == gc.TFLOAT64 {
if gc.Simsimtype(nr.Type) == gc.TFLOAT64 {
if nl.Ullman > nr.Ullman {
gc.Cgen(nl, &tmp)
gc.Cgen(nr, &tmp)
......@@ -853,24 +799,53 @@ x87:
gins(x86.AFSTSW, nil, &ax)
gins(x86.ASAHF, nil, nil)
}
} else {
// Not 387
if !nl.Addable {
nl = gc.CgenTemp(nl)
}
if !nr.Addable {
nr = gc.CgenTemp(nr)
}
var n2 gc.Node
gc.Regalloc(&n2, nr.Type, nil)
gmove(nr, &n2)
nr = &n2
if nl.Op != gc.OREGISTER {
var n3 gc.Node
gc.Regalloc(&n3, nl.Type, nil)
gmove(nl, &n3)
nl = &n3
}
goto ret
if a == gc.OGE || a == gc.OGT {
// only < and <= work right with NaN; reverse if needed
nl, nr = nr, nl
a = gc.Brrev(a)
}
gins(foptoas(gc.OCMP, nr.Type, 0), nl, nr)
if nl.Op == gc.OREGISTER {
gc.Regfree(nl)
}
gc.Regfree(nr)
}
ret:
if a == gc.OEQ {
switch a {
case gc.OEQ:
// neither NE nor P
p1 := gc.Gbranch(x86.AJNE, nil, -likely)
p2 := gc.Gbranch(x86.AJPS, nil, -likely)
gc.Patch(gc.Gbranch(obj.AJMP, nil, 0), to)
gc.Patch(p1, gc.Pc)
gc.Patch(p2, gc.Pc)
} else if a == gc.ONE {
case gc.ONE:
// either NE or P
gc.Patch(gc.Gbranch(x86.AJNE, nil, likely), to)
gc.Patch(gc.Gbranch(x86.AJPS, nil, likely), to)
} else {
default:
gc.Patch(gc.Gbranch(optoas(a, nr.Type), nil, likely), to)
}
}
......
This diff is collapsed.
......@@ -6,10 +6,6 @@ package gc
import "cmd/internal/obj"
func CASE(a int, b int) int {
return a<<16 | b
}
func overlap_cplx(f *Node, t *Node) bool {
// check whether f and t could be overlapping stack references.
// not exact, because it's hard to check for the stack register
......@@ -18,67 +14,52 @@ func overlap_cplx(f *Node, t *Node) bool {
return f.Op == OINDREG && t.Op == OINDREG && f.Xoffset+f.Type.Width >= t.Xoffset && t.Xoffset+t.Type.Width >= f.Xoffset
}
func Complexbool(op int, nl *Node, nr *Node, true_ bool, likely int, to *obj.Prog) {
var tnl Node
func complexbool(op int, nl, nr *Node, wantTrue bool, likely int, to *obj.Prog) {
// make both sides addable in ullman order
if nr != nil {
if nl.Ullman > nr.Ullman && !nl.Addable {
Tempname(&tnl, nl.Type)
Cgen(nl, &tnl)
nl = &tnl
nl = CgenTemp(nl)
}
if !nr.Addable {
var tnr Node
Tempname(&tnr, nr.Type)
Cgen(nr, &tnr)
nr = &tnr
nr = CgenTemp(nr)
}
}
if !nl.Addable {
Tempname(&tnl, nl.Type)
Cgen(nl, &tnl)
nl = &tnl
nl = CgenTemp(nl)
}
// Break nl and nr into real and imaginary components.
var lreal, limag, rreal, rimag Node
subnode(&lreal, &limag, nl)
subnode(&rreal, &rimag, nr)
// build tree
// real(l) == real(r) && imag(l) == imag(r)
var n2 Node
var n1 Node
subnode(&n1, &n2, nl)
var n3 Node
var n4 Node
subnode(&n3, &n4, nr)
var na Node
na.Op = OANDAND
var nb Node
na.Left = &nb
var nc Node
na.Right = &nc
na.Type = Types[TBOOL]
nb = Node{}
nb.Op = OEQ
nb.Left = &n1
nb.Right = &n3
nb.Type = Types[TBOOL]
nc = Node{}
nc.Op = OEQ
nc.Left = &n2
nc.Right = &n4
nc.Type = Types[TBOOL]
realeq := Node{
Op: OEQ,
Left: &lreal,
Right: &rreal,
Type: Types[TBOOL],
}
imageq := Node{
Op: OEQ,
Left: &limag,
Right: &rimag,
Type: Types[TBOOL],
}
and := Node{
Op: OANDAND,
Left: &realeq,
Right: &imageq,
Type: Types[TBOOL],
}
if op == ONE {
true_ = !true_
wantTrue = !wantTrue
}
Bgen(&na, true_, likely, to)
Bgen(&and, wantTrue, likely, to)
}
// break addable nc-complex into nr-real and ni-imaginary
......
......@@ -1091,6 +1091,14 @@ func cgen_callmeth(n *Node, proc int) {
cgen_call(&n2, proc)
}
// CgenTemp creates a temporary node, assigns n to it, and returns it.
func CgenTemp(n *Node) *Node {
var tmp Node
Tempname(&tmp, n.Type)
Cgen(n, &tmp)
return &tmp
}
func checklabels() {
var l *NodeList
......
......@@ -776,7 +776,7 @@ type Arch struct {
AddIndex func(*Node, int64, *Node) bool // optional
Betypeinit func()
Bgen_float func(*Node, int, int, *obj.Prog) // optional
Bgen_float func(*Node, bool, int, *obj.Prog) // optional
Cgen64 func(*Node, *Node) // only on 32-bit systems
Cgenindex func(*Node, *Node, bool) *obj.Prog
Cgen_bmul func(int, *Node, *Node, *Node) bool
......
......@@ -1796,10 +1796,8 @@ func getinargx(t *Type) *Type {
return *getinarg(t)
}
/*
* return !(op)
* eg == <=> !=
*/
// Brcom returns !(op).
// For example, Brcom(==) is !=.
func Brcom(a int) int {
switch a {
case OEQ:
......@@ -1815,15 +1813,12 @@ func Brcom(a int) int {
case OGE:
return OLT
}
Fatal("brcom: no com for %v\n", Oconv(int(a), 0))
Fatal("brcom: no com for %v\n", Oconv(a, 0))
return a
}
/*
* return reverse(op)
* eg a op b <=> b r(op) a
*/
// Brrev returns reverse(op).
// For example, Brrev(<) is >.
func Brrev(a int) int {
switch a {
case OEQ:
......@@ -1839,8 +1834,7 @@ func Brrev(a int) int {
case OGE:
return OLE
}
Fatal("brcom: no rev for %v\n", Oconv(int(a), 0))
Fatal("brrev: no rev for %v\n", Oconv(a, 0))
return a
}
......
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