// Copyright 2016 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. // This file contains rules to decompose [u]int64 types on 32-bit // architectures. These rules work together with the decomposeBuiltIn // pass which handles phis of these typ. (Int64Hi (Int64Make hi _)) -> hi (Int64Lo (Int64Make _ lo)) -> lo (Load ptr mem) && is64BitInt(t) && !config.BigEndian && t.IsSigned() -> (Int64Make (Load (OffPtr [4] ptr) mem) (Load ptr mem)) (Load ptr mem) && is64BitInt(t) && !config.BigEndian && !t.IsSigned() -> (Int64Make (Load (OffPtr [4] ptr) mem) (Load ptr mem)) (Load ptr mem) && is64BitInt(t) && config.BigEndian && t.IsSigned() -> (Int64Make (Load ptr mem) (Load (OffPtr [4] ptr) mem)) (Load ptr mem) && is64BitInt(t) && config.BigEndian && !t.IsSigned() -> (Int64Make (Load ptr mem) (Load (OffPtr [4] ptr) mem)) (Store {t} dst (Int64Make hi lo) mem) && t.(*types.Type).Size() == 8 && !config.BigEndian -> (Store {hi.Type} (OffPtr [4] dst) hi (Store {lo.Type} dst lo mem)) (Store {t} dst (Int64Make hi lo) mem) && t.(*types.Type).Size() == 8 && config.BigEndian -> (Store {lo.Type} (OffPtr [4] dst) lo (Store {hi.Type} dst hi mem)) (Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && v.Type.IsSigned() -> (Int64Make (Arg {n} [off+4]) (Arg {n} [off])) (Arg {n} [off]) && is64BitInt(v.Type) && !config.BigEndian && !v.Type.IsSigned() -> (Int64Make (Arg {n} [off+4]) (Arg {n} [off])) (Arg {n} [off]) && is64BitInt(v.Type) && config.BigEndian && v.Type.IsSigned() -> (Int64Make (Arg {n} [off]) (Arg {n} [off+4])) (Arg {n} [off]) && is64BitInt(v.Type) && config.BigEndian && !v.Type.IsSigned() -> (Int64Make (Arg {n} [off]) (Arg {n} [off+4])) (Add64 x y) -> (Int64Make (Add32withcarry (Int64Hi x) (Int64Hi y) (Select1 (Add32carry (Int64Lo x) (Int64Lo y)))) (Select0 (Add32carry (Int64Lo x) (Int64Lo y)))) (Sub64 x y) -> (Int64Make (Sub32withcarry (Int64Hi x) (Int64Hi y) (Select1 (Sub32carry (Int64Lo x) (Int64Lo y)))) (Select0 (Sub32carry (Int64Lo x) (Int64Lo y)))) (Mul64 x y) -> (Int64Make (Add32 (Mul32 (Int64Lo x) (Int64Hi y)) (Add32 (Mul32 (Int64Hi x) (Int64Lo y)) (Select0 (Mul32uhilo (Int64Lo x) (Int64Lo y))))) (Select1 (Mul32uhilo (Int64Lo x) (Int64Lo y)))) (And64 x y) -> (Int64Make (And32 (Int64Hi x) (Int64Hi y)) (And32 (Int64Lo x) (Int64Lo y))) (Or64 x y) -> (Int64Make (Or32 (Int64Hi x) (Int64Hi y)) (Or32 (Int64Lo x) (Int64Lo y))) (Xor64 x y) -> (Int64Make (Xor32 (Int64Hi x) (Int64Hi y)) (Xor32 (Int64Lo x) (Int64Lo y))) (Neg64 x) -> (Sub64 (Const64 [0]) x) (Com64 x) -> (Int64Make (Com32 (Int64Hi x)) (Com32 (Int64Lo x))) // Sadly, just because we know that x is non-zero, // we don't know whether either component is, // so just treat Ctz64NonZero the same as Ctz64. (Ctz64NonZero x) -> (Ctz64 x) (Ctz64 x) -> (Add32 (Ctz32 (Int64Lo x)) (And32 (Com32 (Zeromask (Int64Lo x))) (Ctz32 (Int64Hi x)))) (BitLen64 x) -> (Add32 (BitLen32 (Int64Hi x)) (BitLen32 (Or32 (Int64Lo x) (Zeromask (Int64Hi x))))) (Bswap64 x) -> (Int64Make (Bswap32 (Int64Lo x)) (Bswap32 (Int64Hi x))) (SignExt32to64 x) -> (Int64Make (Signmask x) x) (SignExt16to64 x) -> (SignExt32to64 (SignExt16to32 x)) (SignExt8to64 x) -> (SignExt32to64 (SignExt8to32 x)) (ZeroExt32to64 x) -> (Int64Make (Const32 [0]) x) (ZeroExt16to64 x) -> (ZeroExt32to64 (ZeroExt16to32 x)) (ZeroExt8to64 x) -> (ZeroExt32to64 (ZeroExt8to32 x)) (Trunc64to32 (Int64Make _ lo)) -> lo (Trunc64to16 (Int64Make _ lo)) -> (Trunc32to16 lo) (Trunc64to8 (Int64Make _ lo)) -> (Trunc32to8 lo) (Lsh32x64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const32 [0]) (Rsh32x64 x (Int64Make (Const32 [c]) _)) && c != 0 -> (Signmask x) (Rsh32Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const32 [0]) (Lsh16x64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const32 [0]) (Rsh16x64 x (Int64Make (Const32 [c]) _)) && c != 0 -> (Signmask (SignExt16to32 x)) (Rsh16Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const32 [0]) (Lsh8x64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const32 [0]) (Rsh8x64 x (Int64Make (Const32 [c]) _)) && c != 0 -> (Signmask (SignExt8to32 x)) (Rsh8Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const32 [0]) (Lsh32x64 x (Int64Make (Const32 [0]) lo)) -> (Lsh32x32 x lo) (Rsh32x64 x (Int64Make (Const32 [0]) lo)) -> (Rsh32x32 x lo) (Rsh32Ux64 x (Int64Make (Const32 [0]) lo)) -> (Rsh32Ux32 x lo) (Lsh16x64 x (Int64Make (Const32 [0]) lo)) -> (Lsh16x32 x lo) (Rsh16x64 x (Int64Make (Const32 [0]) lo)) -> (Rsh16x32 x lo) (Rsh16Ux64 x (Int64Make (Const32 [0]) lo)) -> (Rsh16Ux32 x lo) (Lsh8x64 x (Int64Make (Const32 [0]) lo)) -> (Lsh8x32 x lo) (Rsh8x64 x (Int64Make (Const32 [0]) lo)) -> (Rsh8x32 x lo) (Rsh8Ux64 x (Int64Make (Const32 [0]) lo)) -> (Rsh8Ux32 x lo) (Lsh64x64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const64 [0]) (Rsh64x64 x (Int64Make (Const32 [c]) _)) && c != 0 -> (Int64Make (Signmask (Int64Hi x)) (Signmask (Int64Hi x))) (Rsh64Ux64 _ (Int64Make (Const32 [c]) _)) && c != 0 -> (Const64 [0]) (Lsh64x64 x (Int64Make (Const32 [0]) lo)) -> (Lsh64x32 x lo) (Rsh64x64 x (Int64Make (Const32 [0]) lo)) -> (Rsh64x32 x lo) (Rsh64Ux64 x (Int64Make (Const32 [0]) lo)) -> (Rsh64Ux32 x lo) // turn x64 non-constant shifts to x32 shifts // if high 32-bit of the shift is nonzero, make a huge shift (Lsh64x64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Lsh64x32 x (Or32 (Zeromask hi) lo)) (Rsh64x64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Rsh64x32 x (Or32 (Zeromask hi) lo)) (Rsh64Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Rsh64Ux32 x (Or32 (Zeromask hi) lo)) (Lsh32x64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Lsh32x32 x (Or32 (Zeromask hi) lo)) (Rsh32x64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Rsh32x32 x (Or32 (Zeromask hi) lo)) (Rsh32Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Rsh32Ux32 x (Or32 (Zeromask hi) lo)) (Lsh16x64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Lsh16x32 x (Or32 (Zeromask hi) lo)) (Rsh16x64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Rsh16x32 x (Or32 (Zeromask hi) lo)) (Rsh16Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Rsh16Ux32 x (Or32 (Zeromask hi) lo)) (Lsh8x64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Lsh8x32 x (Or32 (Zeromask hi) lo)) (Rsh8x64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Rsh8x32 x (Or32 (Zeromask hi) lo)) (Rsh8Ux64 x (Int64Make hi lo)) && hi.Op != OpConst32 -> (Rsh8Ux32 x (Or32 (Zeromask hi) lo)) // 64x left shift // result.hi = hi<>(32-s) | lo<<(s-32) // >> is unsigned, large shifts result 0 // result.lo = lo< (Int64Make (Or32 (Or32 (Lsh32x32 hi s) (Rsh32Ux32 lo (Sub32 (Const32 [32]) s))) (Lsh32x32 lo (Sub32 s (Const32 [32])))) (Lsh32x32 lo s)) (Lsh64x16 (Int64Make hi lo) s) -> (Int64Make (Or32 (Or32 (Lsh32x16 hi s) (Rsh32Ux16 lo (Sub16 (Const16 [32]) s))) (Lsh32x16 lo (Sub16 s (Const16 [32])))) (Lsh32x16 lo s)) (Lsh64x8 (Int64Make hi lo) s) -> (Int64Make (Or32 (Or32 (Lsh32x8 hi s) (Rsh32Ux8 lo (Sub8 (Const8 [32]) s))) (Lsh32x8 lo (Sub8 s (Const8 [32])))) (Lsh32x8 lo s)) // 64x unsigned right shift // result.hi = hi>>s // result.lo = lo>>s | hi<<(32-s) | hi>>(s-32) // >> is unsigned, large shifts result 0 (Rsh64Ux32 (Int64Make hi lo) s) -> (Int64Make (Rsh32Ux32 hi s) (Or32 (Or32 (Rsh32Ux32 lo s) (Lsh32x32 hi (Sub32 (Const32 [32]) s))) (Rsh32Ux32 hi (Sub32 s (Const32 [32]))))) (Rsh64Ux16 (Int64Make hi lo) s) -> (Int64Make (Rsh32Ux16 hi s) (Or32 (Or32 (Rsh32Ux16 lo s) (Lsh32x16 hi (Sub16 (Const16 [32]) s))) (Rsh32Ux16 hi (Sub16 s (Const16 [32]))))) (Rsh64Ux8 (Int64Make hi lo) s) -> (Int64Make (Rsh32Ux8 hi s) (Or32 (Or32 (Rsh32Ux8 lo s) (Lsh32x8 hi (Sub8 (Const8 [32]) s))) (Rsh32Ux8 hi (Sub8 s (Const8 [32]))))) // 64x signed right shift // result.hi = hi>>s // result.lo = lo>>s | hi<<(32-s) | (hi>>(s-32))&zeromask(s>>5) // hi>>(s-32) is signed, large shifts result 0/-1 (Rsh64x32 (Int64Make hi lo) s) -> (Int64Make (Rsh32x32 hi s) (Or32 (Or32 (Rsh32Ux32 lo s) (Lsh32x32 hi (Sub32 (Const32 [32]) s))) (And32 (Rsh32x32 hi (Sub32 s (Const32 [32]))) (Zeromask (Rsh32Ux32 s (Const32 [5])))))) (Rsh64x16 (Int64Make hi lo) s) -> (Int64Make (Rsh32x16 hi s) (Or32 (Or32 (Rsh32Ux16 lo s) (Lsh32x16 hi (Sub16 (Const16 [32]) s))) (And32 (Rsh32x16 hi (Sub16 s (Const16 [32]))) (Zeromask (ZeroExt16to32 (Rsh16Ux32 s (Const32 [5]))))))) (Rsh64x8 (Int64Make hi lo) s) -> (Int64Make (Rsh32x8 hi s) (Or32 (Or32 (Rsh32Ux8 lo s) (Lsh32x8 hi (Sub8 (Const8 [32]) s))) (And32 (Rsh32x8 hi (Sub8 s (Const8 [32]))) (Zeromask (ZeroExt8to32 (Rsh8Ux32 s (Const32 [5]))))))) // 64xConst32 shifts // we probably do not need them -- lateopt may take care of them just fine //(Lsh64x32 _ (Const32 [c])) && uint32(c) >= 64 -> (Const64 [0]) //(Rsh64x32 x (Const32 [c])) && uint32(c) >= 64 -> (Int64Make (Signmask (Int64Hi x)) (Signmask (Int64Hi x))) //(Rsh64Ux32 _ (Const32 [c])) && uint32(c) >= 64 -> (Const64 [0]) // //(Lsh64x32 x (Const32 [c])) && c < 64 && c > 32 -> // (Int64Make // (Lsh32x32 (Int64Lo x) (Const32 [c-32])) // (Const32 [0])) //(Rsh64x32 x (Const32 [c])) && c < 64 && c > 32 -> // (Int64Make // (Signmask (Int64Hi x)) // (Rsh32x32 (Int64Hi x) (Const32 [c-32]))) //(Rsh64Ux32 x (Const32 [c])) && c < 64 && c > 32 -> // (Int64Make // (Const32 [0]) // (Rsh32Ux32 (Int64Hi x) (Const32 [c-32]))) // //(Lsh64x32 x (Const32 [32])) -> (Int64Make (Int64Lo x) (Const32 [0])) //(Rsh64x32 x (Const32 [32])) -> (Int64Make (Signmask (Int64Hi x)) (Int64Hi x)) //(Rsh64Ux32 x (Const32 [32])) -> (Int64Make (Const32 [0]) (Int64Hi x)) // //(Lsh64x32 x (Const32 [c])) && c < 32 && c > 0 -> // (Int64Make // (Or32 // (Lsh32x32 (Int64Hi x) (Const32 [c])) // (Rsh32Ux32 (Int64Lo x) (Const32 [32-c]))) // (Lsh32x32 (Int64Lo x) (Const32 [c]))) //(Rsh64x32 x (Const32 [c])) && c < 32 && c > 0 -> // (Int64Make // (Rsh32x32 (Int64Hi x) (Const32 [c])) // (Or32 // (Rsh32Ux32 (Int64Lo x) (Const32 [c])) // (Lsh32x32 (Int64Hi x) (Const32 [32-c])))) //(Rsh64Ux32 x (Const32 [c])) && c < 32 && c > 0 -> // (Int64Make // (Rsh32Ux32 (Int64Hi x) (Const32 [c])) // (Or32 // (Rsh32Ux32 (Int64Lo x) (Const32 [c])) // (Lsh32x32 (Int64Hi x) (Const32 [32-c])))) // //(Lsh64x32 x (Const32 [0])) -> x //(Rsh64x32 x (Const32 [0])) -> x //(Rsh64Ux32 x (Const32 [0])) -> x (Const64 [c]) && t.IsSigned() -> (Int64Make (Const32 [c>>32]) (Const32 [int64(int32(c))])) (Const64 [c]) && !t.IsSigned() -> (Int64Make (Const32 [c>>32]) (Const32 [int64(int32(c))])) (Eq64 x y) -> (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Eq32 (Int64Lo x) (Int64Lo y))) (Neq64 x y) -> (OrB (Neq32 (Int64Hi x) (Int64Hi y)) (Neq32 (Int64Lo x) (Int64Lo y))) (Less64U x y) -> (OrB (Less32U (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Less32U (Int64Lo x) (Int64Lo y)))) (Leq64U x y) -> (OrB (Less32U (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Leq32U (Int64Lo x) (Int64Lo y)))) (Greater64U x y) -> (OrB (Greater32U (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Greater32U (Int64Lo x) (Int64Lo y)))) (Geq64U x y) -> (OrB (Greater32U (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Geq32U (Int64Lo x) (Int64Lo y)))) (Less64 x y) -> (OrB (Less32 (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Less32U (Int64Lo x) (Int64Lo y)))) (Leq64 x y) -> (OrB (Less32 (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Leq32U (Int64Lo x) (Int64Lo y)))) (Greater64 x y) -> (OrB (Greater32 (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Greater32U (Int64Lo x) (Int64Lo y)))) (Geq64 x y) -> (OrB (Greater32 (Int64Hi x) (Int64Hi y)) (AndB (Eq32 (Int64Hi x) (Int64Hi y)) (Geq32U (Int64Lo x) (Int64Lo y))))