| // 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)) |
| } |