blob: 9357de1addceefc02d0eb10c58e47f9c9b41b6ca [file]
// 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.
package rewriteamd64
import (
"cmd/compile/internal/base"
"cmd/compile/internal/ssa"
"cmd/compile/internal/ssa/ssaop"
"cmd/compile/internal/types"
)
// amd64CapAVXShift caps an AMD64 AVX vector shift amount c so that over-shifts
// always result in 0.
//
// These instructions have room for an 8-bit immediate and any value larger than
// the element width will result in 0 or -1 (for an arithmetic right shift).
// Thus, we simply cap this at 255.
func amd64CapAVXShift(auxInt int64) uint8 {
u := ssa.AuxIntToUint64(auxInt)
if u > 255 {
return 255
}
return uint8(u)
}
// flagify rewrites v which is (X ...) to (Select0 (Xflags ...)).
func flagify(v *ssa.Value) bool {
var flagVersion ssaop.Op
switch v.Op {
case ssaop.OpAMD64ADDQconst:
flagVersion = ssaop.OpAMD64ADDQconstflags
case ssaop.OpAMD64ADDLconst:
flagVersion = ssaop.OpAMD64ADDLconstflags
default:
base.Fatalf("can't flagify op %s", v.Op)
}
inner := v.CopyInto(v.Block)
inner.Op = flagVersion
inner.Type = types.NewTuple(v.Type, types.TypeFlags)
v.Reset(ssaop.OpSelect0)
v.AddArg(inner)
return true
}
// sequentialAddresses reports true if it can prove that x + n == y
func sequentialAddresses(x, y *ssa.Value, n int64) bool {
if x == y && n == 0 {
return true
}
if x.Op == ssaop.Op386ADDL && y.Op == ssaop.Op386LEAL1 && y.AuxInt == n && y.Aux == nil &&
(x.Args[0] == y.Args[0] && x.Args[1] == y.Args[1] ||
x.Args[0] == y.Args[1] && x.Args[1] == y.Args[0]) {
return true
}
if x.Op == ssaop.Op386LEAL1 && y.Op == ssaop.Op386LEAL1 && y.AuxInt == x.AuxInt+n && x.Aux == y.Aux &&
(x.Args[0] == y.Args[0] && x.Args[1] == y.Args[1] ||
x.Args[0] == y.Args[1] && x.Args[1] == y.Args[0]) {
return true
}
if x.Op == ssaop.OpAMD64ADDQ && y.Op == ssaop.OpAMD64LEAQ1 && y.AuxInt == n && y.Aux == nil &&
(x.Args[0] == y.Args[0] && x.Args[1] == y.Args[1] ||
x.Args[0] == y.Args[1] && x.Args[1] == y.Args[0]) {
return true
}
if x.Op == ssaop.OpAMD64LEAQ1 && y.Op == ssaop.OpAMD64LEAQ1 && y.AuxInt == x.AuxInt+n && x.Aux == y.Aux &&
(x.Args[0] == y.Args[0] && x.Args[1] == y.Args[1] ||
x.Args[0] == y.Args[1] && x.Args[1] == y.Args[0]) {
return true
}
return false
}
// validVal reports whether the value can be used
// as an argument to makeValAndOff.
func validVal(val int64) bool {
return val == int64(int32(val))
}