mirror of
https://github.com/golang/go
synced 2024-11-23 22:40:04 -07:00
[dev.ssa] cmd/compile: fix fp constant loads for 386+PIC
In position-independent 386 code, loading floating-point constants from the constant pool requires two steps: materializing the address of the constant pool entry (requires calling a thunk) and then loading from that address. Before this CL, the materializing happened implicitly in CX, which clobbered that register. Change-Id: Id094e0fb2d3be211089f299e8f7c89c315de0a87 Reviewed-on: https://go-review.googlesource.com/26811 Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: David Crawshaw <crawshaw@golang.org> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
ed1ad8f56c
commit
8f955d3664
@ -70,8 +70,10 @@
|
||||
(Neg32 x) -> (NEGL x)
|
||||
(Neg16 x) -> (NEGL x)
|
||||
(Neg8 x) -> (NEGL x)
|
||||
(Neg32F x) -> (PXOR x (MOVSSconst <config.Frontend().TypeFloat32()> [f2i(math.Copysign(0, -1))]))
|
||||
(Neg64F x) -> (PXOR x (MOVSDconst <config.Frontend().TypeFloat64()> [f2i(math.Copysign(0, -1))]))
|
||||
(Neg32F x) && !config.use387 -> (PXOR x (MOVSSconst <config.Frontend().TypeFloat32()> [f2i(math.Copysign(0, -1))]))
|
||||
(Neg64F x) && !config.use387 -> (PXOR x (MOVSDconst <config.Frontend().TypeFloat64()> [f2i(math.Copysign(0, -1))]))
|
||||
(Neg32F x) && config.use387 -> (FCHS x)
|
||||
(Neg64F x) && config.use387 -> (FCHS x)
|
||||
|
||||
(Com32 x) -> (NOTL x)
|
||||
(Com16 x) -> (NOTL x)
|
||||
@ -1250,3 +1252,8 @@
|
||||
&& x.Uses == 1
|
||||
&& clobber(x)
|
||||
-> (MOVLstoreidx1 [i-2] {s} p (SHLLconst <idx.Type> [1] idx) w0 mem)
|
||||
|
||||
// For PIC, break floating-point constant loading into two instructions so we have
|
||||
// a register to use for holding the address of the constant pool entry.
|
||||
(MOVSSconst [c]) && config.ctxt.Flag_shared -> (MOVSSconst2 (MOVSSconst1 [c]))
|
||||
(MOVSDconst [c]) && config.ctxt.Flag_shared -> (MOVSDconst2 (MOVSDconst1 [c]))
|
||||
|
@ -463,6 +463,18 @@ func init() {
|
||||
{name: "FlagLT_UGT"}, // signed < and unsigned >
|
||||
{name: "FlagGT_UGT"}, // signed > and unsigned <
|
||||
{name: "FlagGT_ULT"}, // signed > and unsigned >
|
||||
|
||||
// Special op for -x on 387
|
||||
{name: "FCHS", argLength: 1, reg: fp11},
|
||||
|
||||
// Special ops for PIC floating-point constants.
|
||||
// MOVSXconst1 loads the address of the constant-pool entry into a register.
|
||||
// MOVSXconst2 loads the constant from that address.
|
||||
// MOVSXconst1 returns a pointer, but we type it as uint32 because it can never point to the Go heap.
|
||||
{name: "MOVSSconst1", reg: gp01, typ: "UInt32", aux: "Float32"},
|
||||
{name: "MOVSDconst1", reg: gp01, typ: "UInt32", aux: "Float64"},
|
||||
{name: "MOVSSconst2", argLength: 1, reg: gpfp, asm: "MOVSS"},
|
||||
{name: "MOVSDconst2", argLength: 1, reg: gpfp, asm: "MOVSD"},
|
||||
}
|
||||
|
||||
var _386blocks = []blockData{
|
||||
|
@ -345,6 +345,11 @@ const (
|
||||
Op386FlagLT_UGT
|
||||
Op386FlagGT_UGT
|
||||
Op386FlagGT_ULT
|
||||
Op386FCHS
|
||||
Op386MOVSSconst1
|
||||
Op386MOVSDconst1
|
||||
Op386MOVSSconst2
|
||||
Op386MOVSDconst2
|
||||
|
||||
OpAMD64ADDSS
|
||||
OpAMD64ADDSD
|
||||
@ -3675,6 +3680,64 @@ var opcodeTable = [...]opInfo{
|
||||
argLen: 0,
|
||||
reg: regInfo{},
|
||||
},
|
||||
{
|
||||
name: "FCHS",
|
||||
argLen: 1,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVSSconst1",
|
||||
auxType: auxFloat32,
|
||||
argLen: 0,
|
||||
reg: regInfo{
|
||||
outputs: []outputInfo{
|
||||
{0, 239}, // AX CX DX BX BP SI DI
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVSDconst1",
|
||||
auxType: auxFloat64,
|
||||
argLen: 0,
|
||||
reg: regInfo{
|
||||
outputs: []outputInfo{
|
||||
{0, 239}, // AX CX DX BX BP SI DI
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVSSconst2",
|
||||
argLen: 1,
|
||||
asm: x86.AMOVSS,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 239}, // AX CX DX BX BP SI DI
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MOVSDconst2",
|
||||
argLen: 1,
|
||||
asm: x86.AMOVSD,
|
||||
reg: regInfo{
|
||||
inputs: []inputInfo{
|
||||
{0, 239}, // AX CX DX BX BP SI DI
|
||||
},
|
||||
outputs: []outputInfo{
|
||||
{0, 65280}, // X0 X1 X2 X3 X4 X5 X6 X7
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
name: "ADDSS",
|
||||
|
@ -78,6 +78,8 @@ func rewriteValue386(v *Value, config *Config) bool {
|
||||
return rewriteValue386_Op386MOVLstoreidx1(v, config)
|
||||
case Op386MOVLstoreidx4:
|
||||
return rewriteValue386_Op386MOVLstoreidx4(v, config)
|
||||
case Op386MOVSDconst:
|
||||
return rewriteValue386_Op386MOVSDconst(v, config)
|
||||
case Op386MOVSDload:
|
||||
return rewriteValue386_Op386MOVSDload(v, config)
|
||||
case Op386MOVSDloadidx1:
|
||||
@ -90,6 +92,8 @@ func rewriteValue386(v *Value, config *Config) bool {
|
||||
return rewriteValue386_Op386MOVSDstoreidx1(v, config)
|
||||
case Op386MOVSDstoreidx8:
|
||||
return rewriteValue386_Op386MOVSDstoreidx8(v, config)
|
||||
case Op386MOVSSconst:
|
||||
return rewriteValue386_Op386MOVSSconst(v, config)
|
||||
case Op386MOVSSload:
|
||||
return rewriteValue386_Op386MOVSSload(v, config)
|
||||
case Op386MOVSSloadidx1:
|
||||
@ -4213,6 +4217,25 @@ func rewriteValue386_Op386MOVLstoreidx4(v *Value, config *Config) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386MOVSDconst(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVSDconst [c])
|
||||
// cond: config.ctxt.Flag_shared
|
||||
// result: (MOVSDconst2 (MOVSDconst1 [c]))
|
||||
for {
|
||||
c := v.AuxInt
|
||||
if !(config.ctxt.Flag_shared) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386MOVSDconst2)
|
||||
v0 := b.NewValue0(v.Line, Op386MOVSDconst1, config.fe.TypeUInt32())
|
||||
v0.AuxInt = c
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386MOVSDload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
@ -4683,6 +4706,25 @@ func rewriteValue386_Op386MOVSDstoreidx8(v *Value, config *Config) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386MOVSSconst(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (MOVSSconst [c])
|
||||
// cond: config.ctxt.Flag_shared
|
||||
// result: (MOVSSconst2 (MOVSSconst1 [c]))
|
||||
for {
|
||||
c := v.AuxInt
|
||||
if !(config.ctxt.Flag_shared) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386MOVSSconst2)
|
||||
v0 := b.NewValue0(v.Line, Op386MOVSSconst1, config.fe.TypeUInt32())
|
||||
v0.AuxInt = c
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_Op386MOVSSload(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
@ -11399,10 +11441,13 @@ func rewriteValue386_OpNeg32F(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Neg32F x)
|
||||
// cond:
|
||||
// cond: !config.use387
|
||||
// result: (PXOR x (MOVSSconst <config.Frontend().TypeFloat32()> [f2i(math.Copysign(0, -1))]))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if !(!config.use387) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386PXOR)
|
||||
v.AddArg(x)
|
||||
v0 := b.NewValue0(v.Line, Op386MOVSSconst, config.Frontend().TypeFloat32())
|
||||
@ -11410,15 +11455,31 @@ func rewriteValue386_OpNeg32F(v *Value, config *Config) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Neg32F x)
|
||||
// cond: config.use387
|
||||
// result: (FCHS x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if !(config.use387) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386FCHS)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_OpNeg64F(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
_ = b
|
||||
// match: (Neg64F x)
|
||||
// cond:
|
||||
// cond: !config.use387
|
||||
// result: (PXOR x (MOVSDconst <config.Frontend().TypeFloat64()> [f2i(math.Copysign(0, -1))]))
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if !(!config.use387) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386PXOR)
|
||||
v.AddArg(x)
|
||||
v0 := b.NewValue0(v.Line, Op386MOVSDconst, config.Frontend().TypeFloat64())
|
||||
@ -11426,6 +11487,19 @@ func rewriteValue386_OpNeg64F(v *Value, config *Config) bool {
|
||||
v.AddArg(v0)
|
||||
return true
|
||||
}
|
||||
// match: (Neg64F x)
|
||||
// cond: config.use387
|
||||
// result: (FCHS x)
|
||||
for {
|
||||
x := v.Args[0]
|
||||
if !(config.use387) {
|
||||
break
|
||||
}
|
||||
v.reset(Op386FCHS)
|
||||
v.AddArg(x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
func rewriteValue386_OpNeg8(v *Value, config *Config) bool {
|
||||
b := v.Block
|
||||
|
@ -29,6 +29,14 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
|
||||
p.To.Reg = x86.REG_F0
|
||||
popAndSave(s, v)
|
||||
return true
|
||||
case ssa.Op386MOVSSconst2, ssa.Op386MOVSDconst2:
|
||||
p := gc.Prog(loadPush(v.Type))
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = gc.SSARegNum(v.Args[0])
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = x86.REG_F0
|
||||
popAndSave(s, v)
|
||||
return true
|
||||
|
||||
case ssa.Op386MOVSSload, ssa.Op386MOVSDload, ssa.Op386MOVSSloadidx1, ssa.Op386MOVSDloadidx1, ssa.Op386MOVSSloadidx4, ssa.Op386MOVSDloadidx8:
|
||||
p := gc.Prog(loadPush(v.Type))
|
||||
@ -183,28 +191,11 @@ func ssaGenValue387(s *gc.SSAGenState, v *ssa.Value) bool {
|
||||
popAndSave(s, v)
|
||||
return true
|
||||
|
||||
case ssa.Op386PXOR:
|
||||
a0 := v.Args[0]
|
||||
a1 := v.Args[1]
|
||||
for a0.Op == ssa.OpCopy {
|
||||
a0 = a0.Args[0]
|
||||
}
|
||||
for a1.Op == ssa.OpCopy {
|
||||
a1 = a1.Args[0]
|
||||
}
|
||||
if (a0.Op == ssa.Op386MOVSSconst || a0.Op == ssa.Op386MOVSDconst) && a0.AuxInt == -0x8000000000000000 {
|
||||
push(s, v.Args[1])
|
||||
gc.Prog(x86.AFCHS)
|
||||
popAndSave(s, v)
|
||||
return true
|
||||
}
|
||||
if (a1.Op == ssa.Op386MOVSSconst || a1.Op == ssa.Op386MOVSDconst) && a1.AuxInt == -0x8000000000000000 {
|
||||
case ssa.Op386FCHS:
|
||||
push(s, v.Args[0])
|
||||
gc.Prog(x86.AFCHS)
|
||||
popAndSave(s, v)
|
||||
return true
|
||||
}
|
||||
v.Fatalf("PXOR not used to change sign %s", v.LongString())
|
||||
|
||||
case ssa.Op386CVTSL2SS, ssa.Op386CVTSL2SD:
|
||||
p := gc.Prog(x86.AMOVL)
|
||||
|
@ -456,6 +456,27 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
p.From.Val = math.Float64frombits(uint64(v.AuxInt))
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = x
|
||||
case ssa.Op386MOVSSconst1, ssa.Op386MOVSDconst1:
|
||||
var literal string
|
||||
if v.Op == ssa.Op386MOVSDconst1 {
|
||||
literal = fmt.Sprintf("$f64.%016x", uint64(v.AuxInt))
|
||||
} else {
|
||||
literal = fmt.Sprintf("$f32.%08x", math.Float32bits(float32(math.Float64frombits(uint64(v.AuxInt)))))
|
||||
}
|
||||
p := gc.Prog(x86.ALEAL)
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Name = obj.NAME_EXTERN
|
||||
p.From.Sym = obj.Linklookup(gc.Ctxt, literal, 0)
|
||||
p.From.Sym.Local = true
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = gc.SSARegNum(v)
|
||||
case ssa.Op386MOVSSconst2, ssa.Op386MOVSDconst2:
|
||||
p := gc.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
p.From.Reg = gc.SSARegNum(v.Args[0])
|
||||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = gc.SSARegNum(v)
|
||||
|
||||
case ssa.Op386MOVSSload, ssa.Op386MOVSDload, ssa.Op386MOVLload, ssa.Op386MOVWload, ssa.Op386MOVBload, ssa.Op386MOVBLSXload, ssa.Op386MOVWLSXload:
|
||||
p := gc.Prog(v.Op.Asm())
|
||||
p.From.Type = obj.TYPE_MEM
|
||||
@ -872,6 +893,8 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
|
||||
if gc.Debug_checknil != 0 && v.Line > 1 { // v.Line==1 in generated wrappers
|
||||
gc.Warnl(v.Line, "generated nil check")
|
||||
}
|
||||
case ssa.Op386FCHS:
|
||||
v.Fatalf("FCHS in non-387 mode")
|
||||
default:
|
||||
v.Unimplementedf("genValue not implemented: %s", v.LongString())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user