From 7cadf23afb3c54f36758d09710b87a0a9db4b4b9 Mon Sep 17 00:00:00 2001 From: Todd Neal Date: Tue, 25 Aug 2015 22:49:59 -0500 Subject: [PATCH] [dev.ssa] cmd/compile: fix phi floats The code previously always used AX causing errors. For now, just switch off the type in order to at least generate valid code. Change-Id: Iaf13120a24b62456b9b33c04ab31f2d5104b381b Reviewed-on: https://go-review.googlesource.com/13943 Reviewed-by: David Chase --- .../compile/internal/gc/testdata/fp_ssa.go | 46 +++++++++++++++++++ src/cmd/compile/internal/ssa/regalloc.go | 20 ++++++-- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/gc/testdata/fp_ssa.go b/src/cmd/compile/internal/gc/testdata/fp_ssa.go index 95e3cf9196..5eb65035d4 100644 --- a/src/cmd/compile/internal/gc/testdata/fp_ssa.go +++ b/src/cmd/compile/internal/gc/testdata/fp_ssa.go @@ -35,6 +35,52 @@ func manysub_ssa(a, b, c, d float64) (aa, ab, ac, ad, ba, bb, bc, bd, ca, cb, cc return } +// fpspill_ssa attempts to trigger a bug where phis with floating point values +// were stored in non-fp registers causing an error in doasm. +func fpspill_ssa(a int) float64 { + switch { + } + + ret := -1.0 + switch a { + case 0: + ret = 1.0 + case 1: + ret = 1.1 + case 2: + ret = 1.2 + case 3: + ret = 1.3 + case 4: + ret = 1.4 + case 5: + ret = 1.5 + case 6: + ret = 1.6 + case 7: + ret = 1.7 + case 8: + ret = 1.8 + case 9: + ret = 1.9 + case 10: + ret = 1.10 + case 11: + ret = 1.11 + case 12: + ret = 1.12 + case 13: + ret = 1.13 + case 14: + ret = 1.14 + case 15: + ret = 1.15 + case 16: + ret = 1.16 + } + return ret +} + func add64_ssa(a, b float64) float64 { switch { } diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go index b62f9042b6..b098ea1a19 100644 --- a/src/cmd/compile/internal/ssa/regalloc.go +++ b/src/cmd/compile/internal/ssa/regalloc.go @@ -550,6 +550,16 @@ func (s *regAllocState) setState(state []regState) { } } +// compatReg returns a register compatible with the a value and is used when +// spilling/loading. +// TODO: choose a better default register (set of reg by type?). +func compatReg(v *Value) regMask { + if v.Type.IsFloat() { + return 1 << 16 // X0 + } + return 1 << 0 // AX +} + func (s *regAllocState) regalloc(f *Func) { liveset := newSparseSet(f.NumValues()) argset := newSparseSet(f.NumValues()) @@ -836,10 +846,11 @@ func (s *regAllocState) regalloc(f *Func) { if !argset.contains(v.ID) { continue } + // This stack-based phi is the argument of some other // phi in this block. We must make a copy of its // value so that we don't clobber it prematurely. - c := s.allocValToReg(v, s.values[v.ID].regs|1<<0, false) + c := s.allocValToReg(v, s.values[v.ID].regs|compatReg(v), false) d := p.NewValue1(v.Line, OpStoreReg, v.Type, c) s.values[v.ID].spill2 = d } @@ -848,9 +859,10 @@ func (s *regAllocState) regalloc(f *Func) { // we might need a register to do the assignment. for _, v := range stackPhis { // Load phi arg into a register, then store it with a StoreReg. - // If already in a register, use that. If not, use register 0. - // TODO: choose a better default register (set of reg by type?). - c := s.allocValToReg(v.Args[i], s.values[v.Args[i].ID].regs|1<<0, false) + // If already in a register, use that. If not, pick a compatible + // register. + w := v.Args[i] + c := s.allocValToReg(w, s.values[w.ID].regs|compatReg(w), false) v.Args[i] = p.NewValue1(v.Line, OpStoreReg, v.Type, c) } // Figure out what value goes in each register.