Commit 9eb4590a authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: simplify shifts using bounds from prove pass

The prove pass sometimes has bounds information
that later rewrite passes do not.

Use this information to mark shifts as bounded,
and then use that information to generate better code on amd64.
It may prove to be helpful on other architectures, too.

While here, coalesce the existing shift lowering rules.

This triggers 35 times building std+cmd. The full list is below.

Here's an example from runtime.heapBitsSetType:

			if nb < 8 {
				b |= uintptr(*p) << nb
				p = add1(p)
			} else {
				nb -= 8
			}

We now generate better code on amd64 for that left shift.

Updates #25087

vendor/golang_org/x/crypto/curve25519/mont25519_amd64.go:48:20: Proved Rsh8Ux64 bounded
runtime/mbitmap.go:1252:22: Proved Lsh64x64 bounded
runtime/mbitmap.go:1265:16: Proved Lsh64x64 bounded
runtime/mbitmap.go:1275:28: Proved Lsh64x64 bounded
runtime/mbitmap.go:1645:25: Proved Lsh64x64 bounded
runtime/mbitmap.go:1663:25: Proved Lsh64x64 bounded
runtime/mbitmap.go:1808:41: Proved Lsh64x64 bounded
runtime/mbitmap.go:1831:49: Proved Lsh64x64 bounded
syscall/route_bsd.go:227:23: Proved Lsh32x64 bounded
syscall/route_bsd.go:295:23: Proved Lsh32x64 bounded
syscall/route_darwin.go:40:23: Proved Lsh32x64 bounded
compress/bzip2/bzip2.go:384:26: Proved Lsh64x16 bounded
vendor/golang_org/x/net/route/address.go:370:14: Proved Lsh64x64 bounded
compress/flate/inflate.go:201:54: Proved Lsh64x64 bounded
math/big/prime.go:50:25: Proved Lsh64x64 bounded
vendor/golang_org/x/crypto/cryptobyte/asn1.go:464:43: Proved Lsh8x8 bounded
net/ip.go:87:21: Proved Rsh8Ux64 bounded
cmd/internal/goobj/read.go:267:23: Proved Lsh64x64 bounded
cmd/vendor/golang.org/x/arch/arm64/arm64asm/decode.go:534:27: Proved Lsh32x32 bounded
cmd/vendor/golang.org/x/arch/arm64/arm64asm/decode.go:544:27: Proved Lsh32x32 bounded
cmd/internal/obj/arm/asm5.go:1044:16: Proved Lsh32x64 bounded
cmd/internal/obj/arm/asm5.go:1065:10: Proved Lsh32x32 bounded
cmd/internal/obj/mips/obj0.go:1311:21: Proved Lsh32x64 bounded
cmd/compile/internal/syntax/scanner.go:352:23: Proved Lsh64x64 bounded
go/types/expr.go:222:36: Proved Lsh64x64 bounded
crypto/x509/x509.go:1626:9: Proved Rsh8Ux64 bounded
cmd/link/internal/loadelf/ldelf.go:823:22: Proved Lsh8x64 bounded
net/http/h2_bundle.go:1470:17: Proved Lsh8x8 bounded
net/http/h2_bundle.go:1477:46: Proved Lsh8x8 bounded
net/http/h2_bundle.go:1481:31: Proved Lsh64x8 bounded
cmd/compile/internal/ssa/rewriteARM64.go:18759:17: Proved Lsh64x64 bounded
cmd/compile/internal/ssa/sparsemap.go:70:23: Proved Lsh32x64 bounded
cmd/compile/internal/ssa/sparsemap.go:73:45: Proved Lsh32x64 bounded

Change-Id: I58bb72f3e6f12f6ac69be633ea7222c245438142
Reviewed-on: https://go-review.googlesource.com/109776
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarGiovanni Bajo <rasky@develer.com>
parent 22ff9521
......@@ -134,67 +134,37 @@
// Lowering shifts
// Unsigned shifts need to return 0 if shift amount is >= width of shifted value.
// result = (arg << shift) & (shift >= argbits ? 0 : 0xffffffffffffffff)
(Lsh64x64 <t> x y) -> (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMPQconst y [64])))
(Lsh64x32 <t> x y) -> (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMPLconst y [64])))
(Lsh64x16 <t> x y) -> (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMPWconst y [64])))
(Lsh64x8 <t> x y) -> (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMPBconst y [64])))
(Lsh32x64 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPQconst y [32])))
(Lsh32x32 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
(Lsh32x16 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
(Lsh32x8 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
(Lsh16x64 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPQconst y [32])))
(Lsh16x32 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
(Lsh16x16 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
(Lsh16x8 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
(Lsh8x64 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPQconst y [32])))
(Lsh8x32 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
(Lsh8x16 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
(Lsh8x8 <t> x y) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
(Rsh64Ux64 <t> x y) -> (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMPQconst y [64])))
(Rsh64Ux32 <t> x y) -> (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMPLconst y [64])))
(Rsh64Ux16 <t> x y) -> (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMPWconst y [64])))
(Rsh64Ux8 <t> x y) -> (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMPBconst y [64])))
(Rsh32Ux64 <t> x y) -> (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPQconst y [32])))
(Rsh32Ux32 <t> x y) -> (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPLconst y [32])))
(Rsh32Ux16 <t> x y) -> (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPWconst y [32])))
(Rsh32Ux8 <t> x y) -> (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMPBconst y [32])))
(Rsh16Ux64 <t> x y) -> (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPQconst y [16])))
(Rsh16Ux32 <t> x y) -> (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPLconst y [16])))
(Rsh16Ux16 <t> x y) -> (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPWconst y [16])))
(Rsh16Ux8 <t> x y) -> (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMPBconst y [16])))
(Rsh8Ux64 <t> x y) -> (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPQconst y [8])))
(Rsh8Ux32 <t> x y) -> (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPLconst y [8])))
(Rsh8Ux16 <t> x y) -> (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPWconst y [8])))
(Rsh8Ux8 <t> x y) -> (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMPBconst y [8])))
(Lsh64x(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (ANDQ (SHLQ <t> x y) (SBBQcarrymask <t> (CMP(Q|L|W|B)const y [64])))
(Lsh32x(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [32])))
(Lsh16x(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [32])))
(Lsh8x(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (ANDL (SHLL <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [32])))
(Lsh64x(64|32|16|8) x y) && shiftIsBounded(v) -> (SHLQ x y)
(Lsh32x(64|32|16|8) x y) && shiftIsBounded(v) -> (SHLL x y)
(Lsh16x(64|32|16|8) x y) && shiftIsBounded(v) -> (SHLL x y)
(Lsh8x(64|32|16|8) x y) && shiftIsBounded(v) -> (SHLL x y)
(Rsh64Ux(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (ANDQ (SHRQ <t> x y) (SBBQcarrymask <t> (CMP(Q|L|W|B)const y [64])))
(Rsh32Ux(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (ANDL (SHRL <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [32])))
(Rsh16Ux(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (ANDL (SHRW <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [16])))
(Rsh8Ux(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (ANDL (SHRB <t> x y) (SBBLcarrymask <t> (CMP(Q|L|W|B)const y [8])))
(Rsh64Ux(64|32|16|8) x y) && shiftIsBounded(v) -> (SHRQ x y)
(Rsh32Ux(64|32|16|8) x y) && shiftIsBounded(v) -> (SHRL x y)
(Rsh16Ux(64|32|16|8) x y) && shiftIsBounded(v) -> (SHRW x y)
(Rsh8Ux(64|32|16|8) x y) && shiftIsBounded(v) -> (SHRB x y)
// Signed right shift needs to return 0/-1 if shift amount is >= width of shifted value.
// We implement this by setting the shift value to -1 (all ones) if the shift value is >= width.
(Rsh64x64 <t> x y) -> (SARQ <t> x (ORQ <y.Type> y (NOTQ <y.Type> (SBBQcarrymask <y.Type> (CMPQconst y [64])))))
(Rsh64x32 <t> x y) -> (SARQ <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [64])))))
(Rsh64x16 <t> x y) -> (SARQ <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [64])))))
(Rsh64x8 <t> x y) -> (SARQ <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [64])))))
(Rsh32x64 <t> x y) -> (SARL <t> x (ORQ <y.Type> y (NOTQ <y.Type> (SBBQcarrymask <y.Type> (CMPQconst y [32])))))
(Rsh32x32 <t> x y) -> (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [32])))))
(Rsh32x16 <t> x y) -> (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [32])))))
(Rsh32x8 <t> x y) -> (SARL <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [32])))))
(Rsh16x64 <t> x y) -> (SARW <t> x (ORQ <y.Type> y (NOTQ <y.Type> (SBBQcarrymask <y.Type> (CMPQconst y [16])))))
(Rsh16x32 <t> x y) -> (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [16])))))
(Rsh16x16 <t> x y) -> (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [16])))))
(Rsh16x8 <t> x y) -> (SARW <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [16])))))
(Rsh8x64 <t> x y) -> (SARB <t> x (ORQ <y.Type> y (NOTQ <y.Type> (SBBQcarrymask <y.Type> (CMPQconst y [8])))))
(Rsh8x32 <t> x y) -> (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPLconst y [8])))))
(Rsh8x16 <t> x y) -> (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPWconst y [8])))))
(Rsh8x8 <t> x y) -> (SARB <t> x (ORL <y.Type> y (NOTL <y.Type> (SBBLcarrymask <y.Type> (CMPBconst y [8])))))
(Rsh64x(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (SARQ <t> x (OR(Q|L|L|L) <y.Type> y (NOT(Q|L|L|L) <y.Type> (SBB(Q|L|L|L)carrymask <y.Type> (CMP(Q|L|W|B)const y [64])))))
(Rsh32x(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (SARL <t> x (OR(Q|L|L|L) <y.Type> y (NOT(Q|L|L|L) <y.Type> (SBB(Q|L|L|L)carrymask <y.Type> (CMP(Q|L|W|B)const y [32])))))
(Rsh16x(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (SARW <t> x (OR(Q|L|L|L) <y.Type> y (NOT(Q|L|L|L) <y.Type> (SBB(Q|L|L|L)carrymask <y.Type> (CMP(Q|L|W|B)const y [16])))))
(Rsh8x(64|32|16|8) <t> x y) && !shiftIsBounded(v) -> (SARB <t> x (OR(Q|L|L|L) <y.Type> y (NOT(Q|L|L|L) <y.Type> (SBB(Q|L|L|L)carrymask <y.Type> (CMP(Q|L|W|B)const y [8])))))
(Rsh64x(64|32|16|8) x y) && shiftIsBounded(v) -> (SARQ x y)
(Rsh32x(64|32|16|8) x y) && shiftIsBounded(v) -> (SARL x y)
(Rsh16x(64|32|16|8) x y) && shiftIsBounded(v) -> (SARW x y)
(Rsh8x(64|32|16|8) x y) && shiftIsBounded(v) -> (SARB x y)
// Lowering comparisons
(Less(64|32|16|8) x y) -> (SETL (CMP(Q|L|W|B) x y))
......
......@@ -99,56 +99,59 @@ var genericOps = []opData{
// For shifts, AxB means the shifted value has A bits and the shift amount has B bits.
// Shift amounts are considered unsigned.
{name: "Lsh8x8", argLength: 2}, // arg0 << arg1
{name: "Lsh8x16", argLength: 2},
{name: "Lsh8x32", argLength: 2},
{name: "Lsh8x64", argLength: 2},
{name: "Lsh16x8", argLength: 2},
{name: "Lsh16x16", argLength: 2},
{name: "Lsh16x32", argLength: 2},
{name: "Lsh16x64", argLength: 2},
{name: "Lsh32x8", argLength: 2},
{name: "Lsh32x16", argLength: 2},
{name: "Lsh32x32", argLength: 2},
{name: "Lsh32x64", argLength: 2},
{name: "Lsh64x8", argLength: 2},
{name: "Lsh64x16", argLength: 2},
{name: "Lsh64x32", argLength: 2},
{name: "Lsh64x64", argLength: 2},
{name: "Rsh8x8", argLength: 2}, // arg0 >> arg1, signed
{name: "Rsh8x16", argLength: 2},
{name: "Rsh8x32", argLength: 2},
{name: "Rsh8x64", argLength: 2},
{name: "Rsh16x8", argLength: 2},
{name: "Rsh16x16", argLength: 2},
{name: "Rsh16x32", argLength: 2},
{name: "Rsh16x64", argLength: 2},
{name: "Rsh32x8", argLength: 2},
{name: "Rsh32x16", argLength: 2},
{name: "Rsh32x32", argLength: 2},
{name: "Rsh32x64", argLength: 2},
{name: "Rsh64x8", argLength: 2},
{name: "Rsh64x16", argLength: 2},
{name: "Rsh64x32", argLength: 2},
{name: "Rsh64x64", argLength: 2},
{name: "Rsh8Ux8", argLength: 2}, // arg0 >> arg1, unsigned
{name: "Rsh8Ux16", argLength: 2},
{name: "Rsh8Ux32", argLength: 2},
{name: "Rsh8Ux64", argLength: 2},
{name: "Rsh16Ux8", argLength: 2},
{name: "Rsh16Ux16", argLength: 2},
{name: "Rsh16Ux32", argLength: 2},
{name: "Rsh16Ux64", argLength: 2},
{name: "Rsh32Ux8", argLength: 2},
{name: "Rsh32Ux16", argLength: 2},
{name: "Rsh32Ux32", argLength: 2},
{name: "Rsh32Ux64", argLength: 2},
{name: "Rsh64Ux8", argLength: 2},
{name: "Rsh64Ux16", argLength: 2},
{name: "Rsh64Ux32", argLength: 2},
{name: "Rsh64Ux64", argLength: 2},
// If arg1 is known to be less than the number of bits in arg0,
// then aux may be set to true.
// This enables better code generation on some platforms.
{name: "Lsh8x8", argLength: 2, aux: "Bool"}, // arg0 << arg1
{name: "Lsh8x16", argLength: 2, aux: "Bool"},
{name: "Lsh8x32", argLength: 2, aux: "Bool"},
{name: "Lsh8x64", argLength: 2, aux: "Bool"},
{name: "Lsh16x8", argLength: 2, aux: "Bool"},
{name: "Lsh16x16", argLength: 2, aux: "Bool"},
{name: "Lsh16x32", argLength: 2, aux: "Bool"},
{name: "Lsh16x64", argLength: 2, aux: "Bool"},
{name: "Lsh32x8", argLength: 2, aux: "Bool"},
{name: "Lsh32x16", argLength: 2, aux: "Bool"},
{name: "Lsh32x32", argLength: 2, aux: "Bool"},
{name: "Lsh32x64", argLength: 2, aux: "Bool"},
{name: "Lsh64x8", argLength: 2, aux: "Bool"},
{name: "Lsh64x16", argLength: 2, aux: "Bool"},
{name: "Lsh64x32", argLength: 2, aux: "Bool"},
{name: "Lsh64x64", argLength: 2, aux: "Bool"},
{name: "Rsh8x8", argLength: 2, aux: "Bool"}, // arg0 >> arg1, signed
{name: "Rsh8x16", argLength: 2, aux: "Bool"},
{name: "Rsh8x32", argLength: 2, aux: "Bool"},
{name: "Rsh8x64", argLength: 2, aux: "Bool"},
{name: "Rsh16x8", argLength: 2, aux: "Bool"},
{name: "Rsh16x16", argLength: 2, aux: "Bool"},
{name: "Rsh16x32", argLength: 2, aux: "Bool"},
{name: "Rsh16x64", argLength: 2, aux: "Bool"},
{name: "Rsh32x8", argLength: 2, aux: "Bool"},
{name: "Rsh32x16", argLength: 2, aux: "Bool"},
{name: "Rsh32x32", argLength: 2, aux: "Bool"},
{name: "Rsh32x64", argLength: 2, aux: "Bool"},
{name: "Rsh64x8", argLength: 2, aux: "Bool"},
{name: "Rsh64x16", argLength: 2, aux: "Bool"},
{name: "Rsh64x32", argLength: 2, aux: "Bool"},
{name: "Rsh64x64", argLength: 2, aux: "Bool"},
{name: "Rsh8Ux8", argLength: 2, aux: "Bool"}, // arg0 >> arg1, unsigned
{name: "Rsh8Ux16", argLength: 2, aux: "Bool"},
{name: "Rsh8Ux32", argLength: 2, aux: "Bool"},
{name: "Rsh8Ux64", argLength: 2, aux: "Bool"},
{name: "Rsh16Ux8", argLength: 2, aux: "Bool"},
{name: "Rsh16Ux16", argLength: 2, aux: "Bool"},
{name: "Rsh16Ux32", argLength: 2, aux: "Bool"},
{name: "Rsh16Ux64", argLength: 2, aux: "Bool"},
{name: "Rsh32Ux8", argLength: 2, aux: "Bool"},
{name: "Rsh32Ux16", argLength: 2, aux: "Bool"},
{name: "Rsh32Ux32", argLength: 2, aux: "Bool"},
{name: "Rsh32Ux64", argLength: 2, aux: "Bool"},
{name: "Rsh64Ux8", argLength: 2, aux: "Bool"},
{name: "Rsh64Ux16", argLength: 2, aux: "Bool"},
{name: "Rsh64Ux32", argLength: 2, aux: "Bool"},
{name: "Rsh64Ux64", argLength: 2, aux: "Bool"},
// 2-input comparisons
{name: "Eq8", argLength: 2, commutative: true, typ: "Bool"}, // arg0 == arg1
......
......@@ -25022,241 +25022,289 @@ var opcodeTable = [...]opInfo{
},
{
name: "Lsh8x8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh8x16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh8x32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh8x64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh16x8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh16x16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh16x32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh16x64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh32x8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh32x16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh32x32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh32x64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh64x8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh64x16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh64x32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Lsh64x64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh8x8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh8x16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh8x32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh8x64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh16x8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh16x16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh16x32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh16x64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh32x8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh32x16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh32x32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh32x64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh64x8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh64x16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh64x32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh64x64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh8Ux8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh8Ux16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh8Ux32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh8Ux64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh16Ux8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh16Ux16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh16Ux32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh16Ux64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh32Ux8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh32Ux16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh32Ux32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh32Ux64",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh64Ux8",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh64Ux16",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh64Ux32",
auxType: auxBool,
argLen: 2,
generic: true,
},
{
name: "Rsh64Ux64",
auxType: auxBool,
argLen: 2,
generic: true,
},
......
......@@ -972,6 +972,33 @@ func simplifyBlock(sdom SparseTree, ft *factsTable, b *Block) {
}
v.Op = ctzNonZeroOp[v.Op]
}
case OpLsh8x8, OpLsh8x16, OpLsh8x32, OpLsh8x64,
OpLsh16x8, OpLsh16x16, OpLsh16x32, OpLsh16x64,
OpLsh32x8, OpLsh32x16, OpLsh32x32, OpLsh32x64,
OpLsh64x8, OpLsh64x16, OpLsh64x32, OpLsh64x64,
OpRsh8x8, OpRsh8x16, OpRsh8x32, OpRsh8x64,
OpRsh16x8, OpRsh16x16, OpRsh16x32, OpRsh16x64,
OpRsh32x8, OpRsh32x16, OpRsh32x32, OpRsh32x64,
OpRsh64x8, OpRsh64x16, OpRsh64x32, OpRsh64x64,
OpRsh8Ux8, OpRsh8Ux16, OpRsh8Ux32, OpRsh8Ux64,
OpRsh16Ux8, OpRsh16Ux16, OpRsh16Ux32, OpRsh16Ux64,
OpRsh32Ux8, OpRsh32Ux16, OpRsh32Ux32, OpRsh32Ux64,
OpRsh64Ux8, OpRsh64Ux16, OpRsh64Ux32, OpRsh64Ux64:
// Check whether, for a << b, we know that b
// is strictly less than the number of bits in a.
by := v.Args[1]
lim, ok := ft.limits[by.ID]
if !ok {
continue
}
bits := 8 * v.Args[0].Type.Size()
if lim.umax < uint64(bits) || (lim.max < bits && ft.isNonNegative(by)) {
v.Aux = true
if b.Func.pass.debug > 0 {
b.Func.Warnl(v.Pos, "Proved %v bounded", v.Op)
}
}
}
}
......
......@@ -390,6 +390,12 @@ func b2i(b bool) int64 {
return 0
}
// shiftIsBounded reports whether (left/right) shift Value v is known to be bounded.
// A shift is bounded if it is shifting by less than the width of the shifted value.
func shiftIsBounded(v *Value) bool {
return v.Aux != nil && v.Aux.(bool)
}
// i2f is used in rules for converting from an AuxInt to a float.
func i2f(i int64) float64 {
return math.Float64frombits(uint64(i))
......
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