1
0
mirror of https://github.com/golang/go synced 2024-10-02 18:18:33 -06:00

[dev.ssa] cmd/compile: 386 port now works

GOARCH=386 SSATEST=1 ./all.bash passes

Caveat: still needs changes to test/ files to use *_ssa.go versions.  I
won't check those changes in with this CL because the builders will
complain as they don't have SSATEST=1.

Mostly minor fixes.

Implement float <-> uint32 in assembly.  It seems the simplest option
for now.

GO386=387 does not work.  That's why I can't make SSA the default for
386 yet.

Change-Id: Ic4d4402104d32bcfb1fd612f5bb6539f9acb8ae0
Reviewed-on: https://go-review.googlesource.com/25119
Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Keith Randall 2016-07-21 10:37:59 -07:00
parent d8181d5d75
commit df2f813bd2
10 changed files with 168 additions and 24 deletions

View File

@ -95,14 +95,15 @@ const runtimeimport = "" +
"4div\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64div\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x0fint64" +
"mod\x00\x03\n\x00\n\x00\x01\n\x00\t\x11uint64mod\x00\x03\x14\x00\x14\x00\x01\x14\x00\t\x1bfloat6" +
"4toint64\x00\x01\x1a\x00\x01\n\x00\t\x1dfloat64touint64\x00\x01\x1a\x00\x01\x14\x00\t" +
"\x1bint64tofloat64\x00\x01\n\x00\x01\x1a\x00\t\x1duint64tofloat64\x00" +
"\x01\x14\x00\x01\x1a\x00\t\x19complex128div\x00\x04\x1e\vnum·2\x00\x00\x1e\vden·" +
"3\x00\x00\x02\x1e\vquo·1\x00\x00\t\x19racefuncenter\x00\x01\x16d\x00\t\x17race" +
"funcexit\x00\x00\x00\t\x0fraceread\x00\x01\x16d\x00\t\x11racewrite\x00\x01\x16" +
"d\x00\t\x19racereadrange\x00\x04\x16\raddr·1\x00d\x16\rsize·2\x00" +
"d\x00\t\x1bracewriterange\x00\x04\x16\x94\x03\x00d\x16\x96\x03\x00d\x00\t\x0fmsanrea" +
"d\x00\x04\x16\x94\x03\x00d\x16\x96\x03\x00d\x00\t\x11msanwrite\x00\x04\x16\x94\x03\x00d\x16\x96\x03\x00d\x00\v\xf4" +
"\x01\x02\v\x00\x01\x00\n$$\n"
"\x1dfloat64touint32\x00\x01\x1a\x00\x01\x12\x00\t\x1bint64tofloat64\x00" +
"\x01\n\x00\x01\x1a\x00\t\x1duint64tofloat64\x00\x01\x14\x00\x01\x1a\x00\t\x1duint32to" +
"float64\x00\x01\x12\x00\x01\x1a\x00\t\x19complex128div\x00\x04\x1e\vnum·2\x00" +
"\x00\x1e\vden·3\x00\x00\x02\x1e\vquo·1\x00\x00\t\x19racefuncenter\x00\x01\x16" +
"d\x00\t\x17racefuncexit\x00\x00\x00\t\x0fraceread\x00\x01\x16d\x00\t\x11race" +
"write\x00\x01\x16d\x00\t\x19racereadrange\x00\x04\x16\raddr·1\x00d\x16\r" +
"size·2\x00d\x00\t\x1bracewriterange\x00\x04\x16\x98\x03\x00d\x16\x9a\x03\x00d\x00\t" +
"\x0fmsanread\x00\x04\x16\x98\x03\x00d\x16\x9a\x03\x00d\x00\t\x11msanwrite\x00\x04\x16\x98\x03\x00d" +
"\x16\x9a\x03\x00d\x00\v\xf8\x01\x02\v\x00\x01\x00\n$$\n"
const unsafeimport = "" +
"cn\x00\x03v1\x01\vunsafe\x00\x05\r\rPointer\x00\x16\x00\t\x0fOffsetof\x00\x01" +

View File

@ -150,8 +150,10 @@ func int64mod(int64, int64) int64
func uint64mod(uint64, uint64) uint64
func float64toint64(float64) int64
func float64touint64(float64) uint64
func float64touint32(float64) uint32
func int64tofloat64(int64) float64
func uint64tofloat64(uint64) float64
func uint32tofloat64(uint32) float64
func complex128div(num complex128, den complex128) (quo complex128)

View File

@ -4323,7 +4323,7 @@ func CheckLoweredPhi(v *ssa.Value) {
func CheckLoweredGetClosurePtr(v *ssa.Value) {
entry := v.Block.Func.Entry
if entry != v.Block || entry.Values[0] != v {
Fatalf("badly placed LoweredGetClosurePtr: %v %v", v.Block, v)
Fatalf("in %s, badly placed LoweredGetClosurePtr: %v %v", v.Block.Func.Name, v.Block, v)
}
}

View File

@ -1105,6 +1105,39 @@ opswitch:
}
}
if Thearch.LinkArch.Family == sys.I386 {
if n.Left.Type.IsFloat() {
if n.Type.Etype == TINT64 {
n = mkcall("float64toint64", n.Type, init, conv(n.Left, Types[TFLOAT64]))
break
}
if n.Type.Etype == TUINT64 {
n = mkcall("float64touint64", n.Type, init, conv(n.Left, Types[TFLOAT64]))
break
}
if n.Type.Etype == TUINT32 || n.Type.Etype == TUINTPTR {
n = mkcall("float64touint32", n.Type, init, conv(n.Left, Types[TFLOAT64]))
break
}
}
if n.Type.IsFloat() {
if n.Left.Type.Etype == TINT64 {
n = conv(mkcall("int64tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TINT64])), n.Type)
break
}
if n.Left.Type.Etype == TUINT64 {
n = conv(mkcall("uint64tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TUINT64])), n.Type)
break
}
if n.Left.Type.Etype == TUINT32 || n.Left.Type.Etype == TUINTPTR {
n = conv(mkcall("uint32tofloat64", Types[TFLOAT64], init, conv(n.Left, Types[TUINT32])), n.Type)
break
}
}
}
n.Left = walkexpr(n.Left, init)
case OANDNOT:

View File

@ -99,7 +99,7 @@
(ZeroExt16to32 x) -> (MOVWLZX x)
(Signmask x) -> (SARLconst x [31])
(Zeromask x) -> (SBBLcarrymask (CMPL (MOVLconst [0]) x))
(Zeromask <t> x) -> (XORLconst [-1] (SBBLcarrymask <t> (CMPL x (MOVLconst [1]))))
// Lowering truncation
// Because we ignore high parts of registers, truncates are just copies.
@ -183,6 +183,11 @@
(Lsh8x64 _ (Const64 [c])) && uint64(c) >= 8 -> (Const8 [0])
(Rsh8Ux64 _ (Const64 [c])) && uint64(c) >= 8 -> (Const8 [0])
// large constant signed right shift, we leave the sign bit
(Rsh32x64 x (Const64 [c])) && uint64(c) >= 32 -> (SARLconst x [31])
(Rsh16x64 x (Const64 [c])) && uint64(c) >= 16 -> (SARWconst x [15])
(Rsh8x64 x (Const64 [c])) && uint64(c) >= 8 -> (SARBconst x [7])
// Lowering comparisons
(Less32 x y) -> (SETL (CMPL x y))
(Less16 x y) -> (SETL (CMPW x y))

View File

@ -336,9 +336,9 @@
(Lrot64 (Int64Make hi lo) [c]) && c > 32 -> (Lrot64 (Int64Make lo hi) [c-32])
(Const64 <t> [c]) && t.IsSigned() ->
(Int64Make (Const32 <config.fe.TypeInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [c&0xffffffff]))
(Int64Make (Const32 <config.fe.TypeInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [int64(int32(c))]))
(Const64 <t> [c]) && !t.IsSigned() ->
(Int64Make (Const32 <config.fe.TypeUInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [c&0xffffffff]))
(Int64Make (Const32 <config.fe.TypeUInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [int64(int32(c))]))
(Eq64 x y) ->
(AndB

View File

@ -10432,6 +10432,24 @@ func rewriteValue386_OpRsh16x64(v *Value, config *Config) bool {
v.AuxInt = c
return true
}
// match: (Rsh16x64 x (Const64 [c]))
// cond: uint64(c) >= 16
// result: (SARWconst x [15])
for {
x := v.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
c := v_1.AuxInt
if !(uint64(c) >= 16) {
break
}
v.reset(Op386SARWconst)
v.AddArg(x)
v.AuxInt = 15
return true
}
return false
}
func rewriteValue386_OpRsh16x8(v *Value, config *Config) bool {
@ -10647,6 +10665,24 @@ func rewriteValue386_OpRsh32x64(v *Value, config *Config) bool {
v.AuxInt = c
return true
}
// match: (Rsh32x64 x (Const64 [c]))
// cond: uint64(c) >= 32
// result: (SARLconst x [31])
for {
x := v.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
c := v_1.AuxInt
if !(uint64(c) >= 32) {
break
}
v.reset(Op386SARLconst)
v.AddArg(x)
v.AuxInt = 31
return true
}
return false
}
func rewriteValue386_OpRsh32x8(v *Value, config *Config) bool {
@ -10862,6 +10898,24 @@ func rewriteValue386_OpRsh8x64(v *Value, config *Config) bool {
v.AuxInt = c
return true
}
// match: (Rsh8x64 x (Const64 [c]))
// cond: uint64(c) >= 8
// result: (SARBconst x [7])
for {
x := v.Args[0]
v_1 := v.Args[1]
if v_1.Op != OpConst64 {
break
}
c := v_1.AuxInt
if !(uint64(c) >= 8) {
break
}
v.reset(Op386SARBconst)
v.AddArg(x)
v.AuxInt = 7
return true
}
return false
}
func rewriteValue386_OpRsh8x8(v *Value, config *Config) bool {
@ -13015,17 +13069,21 @@ func rewriteValue386_OpZeroExt8to32(v *Value, config *Config) bool {
func rewriteValue386_OpZeromask(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (Zeromask x)
// match: (Zeromask <t> x)
// cond:
// result: (SBBLcarrymask (CMPL (MOVLconst [0]) x))
// result: (XORLconst [-1] (SBBLcarrymask <t> (CMPL x (MOVLconst [1]))))
for {
t := v.Type
x := v.Args[0]
v.reset(Op386SBBLcarrymask)
v0 := b.NewValue0(v.Line, Op386CMPL, TypeFlags)
v1 := b.NewValue0(v.Line, Op386MOVLconst, config.fe.TypeUInt32())
v1.AuxInt = 0
v.reset(Op386XORLconst)
v.AuxInt = -1
v0 := b.NewValue0(v.Line, Op386SBBLcarrymask, t)
v1 := b.NewValue0(v.Line, Op386CMPL, TypeFlags)
v1.AddArg(x)
v2 := b.NewValue0(v.Line, Op386MOVLconst, config.fe.TypeUInt32())
v2.AuxInt = 1
v1.AddArg(v2)
v0.AddArg(v1)
v0.AddArg(x)
v.AddArg(v0)
return true
}

View File

@ -263,7 +263,7 @@ func rewriteValuedec64_OpConst64(v *Value, config *Config) bool {
_ = b
// match: (Const64 <t> [c])
// cond: t.IsSigned()
// result: (Int64Make (Const32 <config.fe.TypeInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [c&0xffffffff]))
// result: (Int64Make (Const32 <config.fe.TypeInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [int64(int32(c))]))
for {
t := v.Type
c := v.AuxInt
@ -275,13 +275,13 @@ func rewriteValuedec64_OpConst64(v *Value, config *Config) bool {
v0.AuxInt = c >> 32
v.AddArg(v0)
v1 := b.NewValue0(v.Line, OpConst32, config.fe.TypeUInt32())
v1.AuxInt = c & 0xffffffff
v1.AuxInt = int64(int32(c))
v.AddArg(v1)
return true
}
// match: (Const64 <t> [c])
// cond: !t.IsSigned()
// result: (Int64Make (Const32 <config.fe.TypeUInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [c&0xffffffff]))
// result: (Int64Make (Const32 <config.fe.TypeUInt32()> [c>>32]) (Const32 <config.fe.TypeUInt32()> [int64(int32(c))]))
for {
t := v.Type
c := v.AuxInt
@ -293,7 +293,7 @@ func rewriteValuedec64_OpConst64(v *Value, config *Config) bool {
v0.AuxInt = c >> 32
v.AddArg(v0)
v1 := b.NewValue0(v.Line, OpConst32, config.fe.TypeUInt32())
v1.AuxInt = c & 0xffffffff
v1.AuxInt = int64(int32(c))
v.AddArg(v1)
return true
}

View File

@ -84,7 +84,7 @@ func schedule(f *Func) {
// Compute score. Larger numbers are scheduled closer to the end of the block.
for _, v := range b.Values {
switch {
case v.Op == OpAMD64LoweredGetClosurePtr || v.Op == OpARMLoweredGetClosurePtr:
case v.Op == OpAMD64LoweredGetClosurePtr || v.Op == OpARMLoweredGetClosurePtr || v.Op == Op386LoweredGetClosurePtr:
// We also score GetLoweredClosurePtr as early as possible to ensure that the
// context register is not stomped. GetLoweredClosurePtr should only appear
// in the entry block where there are no phi functions, so there is no

View File

@ -1637,3 +1637,48 @@ TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0
MOVL AX, moduledata_next(DX)
MOVL AX, runtime·lastmoduledatap(SB)
RET
TEXT runtime·uint32tofloat64(SB),NOSPLIT,$0-12
// TODO: condition on GO386 env var.
MOVL a+0(FP), AX
// Check size.
CMPL AX, $0x80000000
JAE large
// Less than 2**31, convert directly.
CVTSL2SD AX, X0
MOVSD X0, ret+4(FP)
RET
large:
// >= 2**31. Subtract 2**31 (uint32), convert, then add 2**31 (float64).
SUBL $0x80000000, AX
CVTSL2SD AX, X0
ADDSD twotothe31<>(SB), X0
MOVSD X0, ret+4(FP)
RET
TEXT runtime·float64touint32(SB),NOSPLIT,$0-12
// TODO: condition on GO386 env var.
MOVSD a+0(FP), X0
// Check size.
MOVSD twotothe31<>(SB), X1
UCOMISD X1, X0 //note: args swapped relative to CMPL
JAE large
// Less than 2**31, convert directly.
CVTTSD2SL X0, AX
MOVL AX, ret+8(FP)
RET
large:
// >= 2**31. Subtract 2**31 (float64), convert, then add 2**31 (uint32).
SUBSD X1, X0
CVTTSD2SL X0, AX
ADDL $0x80000000, AX
MOVL AX, ret+8(FP)
RET
// 2**31 as a float64.
DATA twotothe31<>+0x00(SB)/8, $0x41e0000000000000
GLOBL twotothe31<>(SB),RODATA,$8