diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index f9a43af361..bf45fb2e45 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -336,7 +336,6 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { // Result[0] (the quotient) is in AX. // Result[1] (the remainder) is in DX. r := v.Args[1].Reg() - var j1 *obj.Prog var opCMP, opNEG, opSXD obj.As switch v.Op { @@ -350,28 +349,19 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { // CPU faults upon signed overflow, which occurs when the most // negative int is divided by -1. Handle divide by -1 as a special case. + var j1, j2 *obj.Prog if ssa.DivisionNeedsFixUp(v) { c := s.Prog(opCMP) c.From.Type = obj.TYPE_REG c.From.Reg = r c.To.Type = obj.TYPE_CONST c.To.Offset = -1 - j1 = s.Prog(x86.AJEQ) + + // Divisor is not -1, proceed with normal division. + j1 = s.Prog(x86.AJNE) j1.To.Type = obj.TYPE_BRANCH - } - // Sign extend dividend and perform division. - s.Prog(opSXD) - p := s.Prog(v.Op.Asm()) - p.From.Type = obj.TYPE_REG - p.From.Reg = r - - if j1 != nil { - // Skip over -1 fixup code. - j2 := s.Prog(obj.AJMP) - j2.To.Type = obj.TYPE_BRANCH - - // Issue -1 fixup code. + // Divisor is -1, manually compute quotient and remainder via fixup code. // n / -1 = -n n1 := s.Prog(opNEG) n1.To.Type = obj.TYPE_REG @@ -383,7 +373,21 @@ func ssaGenValue(s *ssagen.State, v *ssa.Value) { // TODO(khr): issue only the -1 fixup code we need. // For instance, if only the quotient is used, no point in zeroing the remainder. - j1.To.SetTarget(n1) + // Skip over normal division. + j2 = s.Prog(obj.AJMP) + j2.To.Type = obj.TYPE_BRANCH + } + + // Sign extend dividend and perform division. + p := s.Prog(opSXD) + if j1 != nil { + j1.To.SetTarget(p) + } + p = s.Prog(v.Op.Asm()) + p.From.Type = obj.TYPE_REG + p.From.Reg = r + + if j2 != nil { j2.To.SetTarget(s.Pc()) }