Commit 03c81648 authored by Russ Cox's avatar Russ Cox

cmd/compile: fix magic multiply smashing AX

Fixes #12411.

Change-Id: I2202a754c7750e3b2119e3744362c98ca0d2433e
Reviewed-on: https://go-review.googlesource.com/17818Reviewed-by: default avatarKeith Randall <khr@golang.org>
Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 63a6f305
...@@ -365,24 +365,25 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) { ...@@ -365,24 +365,25 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
gc.Cgenr(nl, &n1, res) gc.Cgenr(nl, &n1, res)
var n2 gc.Node var n2 gc.Node
gc.Cgenr(nr, &n2, nil) gc.Cgenr(nr, &n2, nil)
var ax gc.Node var ax, oldax, dx, olddx gc.Node
gc.Nodreg(&ax, t, x86.REG_AX) savex(x86.REG_AX, &ax, &oldax, res, gc.Types[gc.TUINT64])
savex(x86.REG_DX, &dx, &olddx, res, gc.Types[gc.TUINT64])
gmove(&n1, &ax) gmove(&n1, &ax)
gins(a, &n2, nil) gins(a, &n2, nil)
gc.Regfree(&n2) gc.Regfree(&n2)
gc.Regfree(&n1) gc.Regfree(&n1)
var dx gc.Node
if t.Width == 1 { if t.Width == 1 {
// byte multiply behaves differently. // byte multiply behaves differently.
gc.Nodreg(&ax, t, x86.REG_AH) var byteAH, byteDX gc.Node
gc.Nodreg(&byteAH, t, x86.REG_AH)
gc.Nodreg(&dx, t, x86.REG_DX) gc.Nodreg(&byteDX, t, x86.REG_DX)
gmove(&ax, &dx) gmove(&byteAH, &byteDX)
} }
gc.Nodreg(&dx, t, x86.REG_DX)
gmove(&dx, res) gmove(&dx, res)
restx(&ax, &oldax)
restx(&dx, &olddx)
} }
/* /*
......
...@@ -531,24 +531,21 @@ func cgen_bmul(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) bool { ...@@ -531,24 +531,21 @@ func cgen_bmul(op gc.Op, nl *gc.Node, nr *gc.Node, res *gc.Node) bool {
func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) { func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
var n1 gc.Node var n1 gc.Node
var n2 gc.Node var n2 gc.Node
var ax gc.Node
var dx gc.Node
t := nl.Type t := nl.Type
a := optoas(gc.OHMUL, t) a := optoas(gc.OHMUL, t)
// gen nl in n1. // gen nl in n1.
gc.Tempname(&n1, t) gc.Tempname(&n1, t)
gc.Cgen(nl, &n1) gc.Cgen(nl, &n1)
// gen nr in n2. // gen nr in n2.
gc.Regalloc(&n2, t, res) gc.Regalloc(&n2, t, res)
gc.Cgen(nr, &n2) gc.Cgen(nr, &n2)
// multiply. var ax, oldax, dx, olddx gc.Node
gc.Nodreg(&ax, t, x86.REG_AX) savex(x86.REG_AX, &ax, &oldax, res, gc.Types[gc.TUINT32])
savex(x86.REG_DX, &dx, &olddx, res, gc.Types[gc.TUINT32])
gmove(&n2, &ax) gmove(&n2, &ax)
gins(a, &n1, nil) gins(a, &n1, nil)
...@@ -556,14 +553,16 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) { ...@@ -556,14 +553,16 @@ func cgen_hmul(nl *gc.Node, nr *gc.Node, res *gc.Node) {
if t.Width == 1 { if t.Width == 1 {
// byte multiply behaves differently. // byte multiply behaves differently.
gc.Nodreg(&ax, t, x86.REG_AH) var byteAH, byteDX gc.Node
gc.Nodreg(&byteAH, t, x86.REG_AH)
gc.Nodreg(&dx, t, x86.REG_DX) gc.Nodreg(&byteDX, t, x86.REG_DX)
gmove(&ax, &dx) gmove(&byteAH, &byteDX)
} }
gc.Nodreg(&dx, t, x86.REG_DX)
gmove(&dx, res) gmove(&dx, res)
restx(&ax, &oldax)
restx(&dx, &olddx)
} }
/* /*
......
// +build !386
// run
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 12411. Loss of AX during %.
package main
func main() {
x := f(4)
if x != 0 {
println("BUG: x=", x)
}
}
//go:noinline
func f(x int) int {
// AX was live on entry to one of the % code generations,
// and the % code generation smashed it.
return ((2 * x) % 3) % (2 % ((x << 2) ^ (x % 3)))
}
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