Repository: go
Issue: cmd/compile: simplify multiplication and division of Abs() 
Labels: Performance,NeedsDecision,compiler/runtime

<!--
Please answer these questions before submitting your issue. Thanks!
-->

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.16.8 linux/amd64
</pre>

### Does this issue reproduce with the latest release?
Yes. See https://go.godbolt.org/z/1Gq4bPPnd for assembly output.


### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/jacob/.cache/go-build"
GOENV="/home/jacob/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/jacob/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/jacob/go"
GOPRIVATE=""
GOPROXY="direct"
GOROOT="/usr/lib/golang"
GOSUMDB="off"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.8"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build3228184624=/tmp/go-build -gno-record-gcc-switches"

</pre></details>

### What did you do?

<!--
If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on go.dev/play is best.
-->

I noticed that the compile doesn't optimize calls to `math.Abs()` or `cmplx.Abs()` to strip out unnecessary calls to those functions when multiplying them or dividing them. According to the absolute value rules, `|A * B| = |A| * |B|` and `|A / B| = |A| / |B|`, meaning that the compiler should be able to work the right two calls to either `math.Abs()` or `cmplx.Abs()` into a single call by moving the multiplication or division inside the call instead.

This means that the first block of assembly can be simplified to the one after.

```asm
        MOVQ    X0, AX
        BTRQ    $63, AX
        MOVQ    AX, X0
        MOVQ    X1, AX
        BTRQ    $63, AX
        MOVQ    AX, X1
        MULSD   X1, X0
```

```asm
        MULSD   X1, X0
        MOVQ    X0, AX
        BTRQ    $63, AX
        MOVQ    AX, X0
```

The above assembly was taken from the multiplication examples below:

```go
func AbsMult(x, y float64) float64 {
    return math.Abs(x) * math.Abs(y)
}

func AbsMultSimple(x, y float64) float64 {
    return math.Abs(x * y)
}

func AbsDiv(x, y float64) float64 {
    return math.Abs(x) / math.Abs(y)
}

func AbsDivSimple(x, y float64) float64 {
    return math.Abs(x / y)
}
```

This should also apply to complex numbers. It is important to note that it is only for multiplication and division, not addition and subtraction.

### What did you expect to see?
I expected the compiler to strip out the duplicated calls to `math.Abs()`. Thus getting the following assembly for the `AbsMult` function below.

```asm
        MULSD   X1, X0
        MOVQ    X0, AX
        BTRQ    $63, AX
        MOVQ    AX, X0
```

### What did you see instead?

The compiler did not strip it out:

```asm
        MOVQ    X0, AX
        BTRQ    $63, AX
        MOVQ    AX, X0
        MOVQ    X1, AX
        BTRQ    $63, AX
        MOVQ    AX, X1
        MULSD   X1, X0
```

For more info, see: https://github.com/dominikh/go-tools/issues/1135