Commit graph

91 commits

Author SHA1 Message Date
David Chase
62cd044a79 cmd/compile: add cases for StringLen to prove
Tricky index-offset logic had been added for slices,
but not for strings.  This fixes that, and also adds
tests for same behavior in string/slice cases, and adds
a new test for code in prove that had been added but not
explicitly tested.

Fixes #76270.

Change-Id: Ibd92b89e944d86b7f30b4486a9008e6f1ac6af7d
Reviewed-on: https://go-review.googlesource.com/c/go/+/723980
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2025-11-24 15:49:12 -08:00
Jorropo
ec92bc6d63 cmd/compile: rewrite Rsh to RshU if arguments are proved positive
Fixes #76332

Change-Id: I9044025d5dc599531c7f88ed2870bcf3d8b0acbd
Reviewed-on: https://go-review.googlesource.com/c/go/+/721206
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
2025-11-21 12:37:30 -08:00
Jorropo
3820f94c1d cmd/compile: propagate unsigned relations for Rsh if arguments are positive
Updates #76332

Change-Id: Ifaa4d12897138d88d56b9d4e530c53dcee70bd58
Reviewed-on: https://go-review.googlesource.com/c/go/+/721205
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Keith Randall <khr@google.com>
2025-11-21 12:37:27 -08:00
Jakub Ciolek
f87aaec53d cmd/compile: fix integer overflow in prove pass
The detectSliceLenRelation function incorrectly deduced lower bounds
for "len(s) - i" without checking if the subtraction could overflow
(e.g. when i is negative). This led to incorrect elimination of
bounds checks.

Fixes: #76355
Change-Id: I30ada0e5f1425929ddd8ae1b66e55096ec209b5b
Reviewed-on: https://go-review.googlesource.com/c/go/+/721920
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@google.com>
2025-11-21 10:34:21 -08:00
Jorropo
2239520d1c test: go fmt prove.go tests
Change-Id: Ia4c2ceffcf2bfde862e9dba02a4b38245f868692
Reviewed-on: https://go-review.googlesource.com/c/go/+/721202
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Sean Liao <sean@liao.dev>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
2025-11-19 13:33:52 -08:00
Keith Randall
c12c337099 cmd/compile: teach prove about subtract idioms
For v = x-y:
    if y >= 0 then v <= x
    if y <= x then v >= 0

(With appropriate guards against overflow/underflow.)

Fixes #76304

Change-Id: I8f8f1254156c347fa97802bd057a8379676720ae
Reviewed-on: https://go-review.googlesource.com/c/go/+/720740
Reviewed-by: Mark Freeman <markfreeman@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
2025-11-17 09:48:53 -08:00
Russ Cox
235b4e729d cmd/compile/internal/ssa: model right shift more precisely
Prove currently checks for 0 sign bit extraction (x>>63) at the
end of the pass, but it is more general and more useful
(and not really more work) to model right shift during
value range tracking. This handles sign bit extraction (both 0 and -1)
but also makes the value ranges available for proving bounds checks.

'go build -a -gcflags=-d=ssa/prove/debug=1 std'
finds 105 new things to prove.
https://gist.github.com/rsc/8ac41176e53ed9c2f1a664fc668e8336

For example, the compiler now recognizes that this code in
strconv does not need to check the second shift for being ≥ 64.

	msb := xHi >> 63
	retMantissa := xHi >> (msb + 38)

nor does this code in regexp:

	return b < utf8.RuneSelf && specialBytes[b%16]&(1<<(b/16)) != 0

This code in math no longer has a bounds check on the first index:

	if 0 <= n && n <= 308 {
		return pow10postab32[uint(n)/32] * pow10tab[uint(n)%32]
	}

The diff shows one "lost" proof in ycbcr.go but it's not really lost:
the expression was folded to a constant instead, and that only shows
up with debug=2. A diff of that output is at
https://gist.github.com/rsc/9139ed46c6019ae007f5a1ba4bb3250f

Change-Id: I84087311e0a303f00e2820d957a6f8b29ee22519
Reviewed-on: https://go-review.googlesource.com/c/go/+/716140
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2025-10-30 09:17:59 -07:00
Russ Cox
9bbda7c99d cmd/compile: make prove understand div, mod better
This CL introduces new divisible and divmod passes that rewrite
divisibility checks and div, mod, and mul. These happen after
prove, so that prove can make better sense of the code for
deriving bounds, and they must run before decompose, so that
64-bit ops can be lowered to 32-bit ops on 32-bit systems.
And then they need another generic pass as well, to optimize
the generated code before decomposing.

The three opt passes are "opt", "middle opt", and "late opt".
(Perhaps instead they should be "generic", "opt", and "late opt"?)

The "late opt" pass repeats the "middle opt" work on any new code
that has been generated in the interim.
There will not be new divs or mods, but there may be new muls.

The x%c==0 rewrite rules are much simpler now, since they can
match before divs have been rewritten. This has the effect of
applying them more consistently and making the rewrite rules
independent of the exact div rewrites.

Prove is also now charged with marking signed div/mod as
unsigned when the arguments call for it, allowing simpler
code to be emitted in various cases. For example,
t.Seconds()/2 and len(x)/2 are now recognized as unsigned,
meaning they compile to a simple shift (unsigned division),
avoiding the more complex fixup we need for signed values.

https://gist.github.com/rsc/99d9d3bd99cde87b6a1a390e3d85aa32
shows a diff of 'go build -a -gcflags=-d=ssa/prove/debug=1 std'
output before and after. "Proved Rsh64x64 shifts to zero" is replaced
by the higher-level "Proved Div64 is unsigned" (the shift was in the
signed expansion of div by constant), but otherwise prove is only
finding more things to prove.

One short example, in code that does x[i%len(x)]:

< runtime/mfinal.go:131:34: Proved Rsh64x64 shifts to zero
---
> runtime/mfinal.go:131:34: Proved Div64 is unsigned
> runtime/mfinal.go:131:38: Proved IsInBounds

A longer example:

< crypto/internal/fips140/sha3/shake.go:28:30: Proved Rsh64x64 shifts to zero
< crypto/internal/fips140/sha3/shake.go:38:27: Proved Rsh64x64 shifts to zero
< crypto/internal/fips140/sha3/shake.go:53:46: Proved Rsh64x64 shifts to zero
< crypto/internal/fips140/sha3/shake.go:55:46: Proved Rsh64x64 shifts to zero
---
> crypto/internal/fips140/sha3/shake.go:28:30: Proved Div64 is unsigned
> crypto/internal/fips140/sha3/shake.go:28:30: Proved IsInBounds
> crypto/internal/fips140/sha3/shake.go:28:30: Proved IsSliceInBounds
> crypto/internal/fips140/sha3/shake.go:38:27: Proved Div64 is unsigned
> crypto/internal/fips140/sha3/shake.go:45:7: Proved IsSliceInBounds
> crypto/internal/fips140/sha3/shake.go:46:4: Proved IsInBounds
> crypto/internal/fips140/sha3/shake.go:53:46: Proved Div64 is unsigned
> crypto/internal/fips140/sha3/shake.go:53:46: Proved IsInBounds
> crypto/internal/fips140/sha3/shake.go:53:46: Proved IsSliceInBounds
> crypto/internal/fips140/sha3/shake.go:55:46: Proved Div64 is unsigned
> crypto/internal/fips140/sha3/shake.go:55:46: Proved IsInBounds
> crypto/internal/fips140/sha3/shake.go:55:46: Proved IsSliceInBounds

These diffs are due to the smaller opt being better
and taking work away from prove:

< image/jpeg/dct.go:307:5: Proved IsInBounds
< image/jpeg/dct.go:308:5: Proved IsInBounds
...
< image/jpeg/dct.go:442:5: Proved IsInBounds

In the old opt, Mul by 8 was rewritten to Lsh by 3 early.
This CL delays that rule to help prove recognize mods,
but it also helps opt constant-fold the slice x[8*i:8*i+8:8*i+8].
Specifically, computing the length, opt can now do:

	(Sub64 (Add (Mul 8 i) 8) (Add (Mul 8 i) 8)) ->
	(Add 8 (Sub (Mul 8 i) (Mul 8 i))) ->
	(Add 8 (Mul 8 (Sub i i))) ->
	(Add 8 (Mul 8 0)) ->
	(Add 8 0) ->
	8

The key step is (Sub (Mul x y) (Mul x z)) -> (Mul x (Sub y z)),
Leaving the multiply as Mul enables using that step; the old
rewrite to Lsh blocked it, leaving prove to figure out the length
and then remove the bounds checks. But now opt can evaluate
the length down to a constant 8 and then constant-fold away
the bounds checks 0 < 8, 1 < 8, and so on. After that,
the compiler has nothing left to prove.

Benchmarks are noisy in general; I checked the assembly for the many
large increases below, and the vast majority are unchanged and
presumably hitting the caches differently in some way.

The divisibility optimizations were not reliably triggering before.
This leads to a very large improvement in some cases, like
DivisiblePow2constI64, DivisibleconstI64 on 64-bit systems
and DivisbleconstU64 on 32-bit systems.

Another way the divisibility optimizations were unreliable before
was incorrectly triggering for x/3, x%3 even though they are
written not to do that. There is a real but small slowdown
in the DivisibleWDivconst benchmarks on Mac because in the cases
used in the benchmark, it is still faster (on Mac) to do the
divisibility check than to remultiply.
This may be worth further study. Perhaps when there is no rotate
(meaning the divisor is odd), the divisibility optimization
should be enabled always. In any event, this CL makes it possible
to study that.

benchmark \ host                          s7  linux-amd64      mac  linux-arm64  linux-ppc64le  linux-386  s7:GOARCH=386  linux-arm
                                     vs base      vs base  vs base      vs base        vs base    vs base        vs base    vs base
LoadAdd                                    ~            ~        ~            ~              ~     -1.59%              ~          ~
ExtShift                                   ~            ~  -42.14%       +0.10%              ~     +1.44%         +5.66%     +8.50%
Modify                                     ~            ~        ~            ~              ~          ~              ~     -1.53%
MullImm                                    ~            ~        ~            ~              ~    +37.90%        -21.87%     +3.05%
ConstModify                                ~            ~        ~            ~        -49.14%          ~              ~          ~
BitSet                                     ~            ~        ~            ~        -15.86%    -14.57%         +6.44%     +0.06%
BitClear                                   ~            ~        ~            ~              ~     +1.78%         +3.50%     +0.06%
BitToggle                                  ~            ~        ~            ~              ~    -16.09%         +2.91%          ~
BitSetConst                                ~            ~        ~            ~              ~          ~              ~     -0.49%
BitClearConst                              ~            ~        ~            ~        -28.29%          ~              ~     -0.40%
BitToggleConst                             ~            ~        ~       +8.89%        -31.19%          ~              ~     -0.77%
MulNeg                                     ~            ~        ~            ~              ~          ~              ~          ~
Mul2Neg                                    ~            ~   -4.83%            ~              ~    -13.75%         -5.92%          ~
DivconstI64                                ~            ~        ~            ~              ~    -30.12%              ~     +0.50%
ModconstI64                                ~            ~   -9.94%       -4.63%              ~     +3.15%              ~     +5.32%
DivisiblePow2constI64                -34.49%      -12.58%        ~            ~        -12.25%          ~              ~          ~
DivisibleconstI64                    -24.69%      -25.06%   -0.40%       -2.27%        -42.61%     -3.31%              ~     +1.63%
DivisibleWDivconstI64                      ~            ~        ~            ~              ~    -17.55%              ~     -0.60%
DivconstU64/3                              ~            ~        ~            ~              ~     +1.51%              ~          ~
DivconstU64/5                              ~            ~        ~            ~              ~          ~              ~          ~
DivconstU64/37                             ~            ~   -0.18%            ~              ~     +2.70%              ~          ~
DivconstU64/1234567                        ~            ~        ~            ~              ~          ~              ~     +0.12%
ModconstU64                                ~            ~        ~       -0.24%              ~     -5.10%         -1.07%     -1.56%
DivisibleconstU64                          ~            ~        ~            ~              ~    -29.01%        -59.13%    -50.72%
DivisibleWDivconstU64                      ~            ~  -12.18%      -18.88%              ~     -5.50%         -3.91%     +5.17%
DivconstI32                                ~            ~   -0.48%            ~        -34.69%    +89.01%         -6.01%    -16.67%
ModconstI32                                ~       +2.95%   -0.33%            ~              ~     -2.98%         -5.40%     -8.30%
DivisiblePow2constI32                      ~            ~        ~            ~              ~          ~              ~    -16.22%
DivisibleconstI32                          ~            ~        ~            ~              ~    -37.27%        -47.75%    -25.03%
DivisibleWDivconstI32                -11.59%       +5.22%  -12.99%      -23.83%              ~    +45.95%         -7.03%    -10.01%
DivconstU32                                ~            ~        ~            ~              ~    +74.71%         +4.81%          ~
ModconstU32                                ~            ~   +0.53%       +0.18%              ~    +51.16%              ~          ~
DivisibleconstU32                          ~            ~        ~       -0.62%              ~     -4.25%              ~          ~
DivisibleWDivconstU32                 -2.77%       +5.56%  +11.12%       -5.15%              ~    +48.70%        +25.11%     -4.07%
DivconstI16                           -6.06%            ~   -0.33%       +0.22%              ~          ~         -9.68%     +5.47%
ModconstI16                                ~            ~   +4.44%       +2.82%              ~          ~              ~     +5.06%
DivisiblePow2constI16                      ~            ~        ~            ~              ~          ~              ~     -0.17%
DivisibleconstI16                          ~            ~   -0.23%            ~              ~          ~         +4.60%     +6.64%
DivisibleWDivconstI16                 -1.44%       -0.43%  +13.48%       -5.76%              ~     +1.62%        -23.15%     -9.06%
DivconstU16                           +1.61%            ~   -0.35%       -0.47%              ~          ~        +15.59%          ~
ModconstU16                                ~            ~        ~            ~              ~     -0.72%              ~    +14.23%
DivisibleconstU16                          ~            ~   -0.05%       +3.00%              ~          ~              ~     +5.06%
DivisibleWDivconstU16                +52.10%       +0.75%  +17.28%       +4.79%              ~    -37.39%         +5.28%     -9.06%
DivconstI8                                 ~            ~   -0.34%       -0.96%              ~          ~         -9.20%          ~
ModconstI8                            +2.29%            ~   +4.38%       +2.96%              ~          ~              ~          ~
DivisiblePow2constI8                       ~            ~        ~            ~              ~          ~              ~          ~
DivisibleconstI8                           ~            ~        ~            ~              ~          ~         +6.04%          ~
DivisibleWDivconstI8                 -26.44%       +1.69%  +17.03%       +4.05%              ~    +32.48%        -24.90%          ~
DivconstU8                            -4.50%      +14.06%   -0.28%            ~              ~          ~         +4.16%     +0.88%
ModconstU8                                 ~            ~  +25.84%       -0.64%              ~          ~              ~          ~
DivisibleconstU8                           ~            ~   -5.70%            ~              ~          ~              ~          ~
DivisibleWDivconstU8                 +49.55%       +9.07%        ~       +4.03%        +53.87%    -40.03%        +39.72%     -3.01%
Mul2                                       ~            ~        ~            ~              ~          ~              ~          ~
MulNeg2                                    ~            ~        ~            ~        -11.73%          ~              ~     -0.02%
EfaceInteger                               ~            ~        ~            ~              ~    +18.11%              ~     +2.53%
TypeAssert                           +33.90%       +2.86%        ~            ~              ~     -1.07%         -5.29%     -1.04%
Div64UnsignedSmall                         ~            ~        ~            ~              ~          ~              ~          ~
Div64Small                                 ~            ~        ~            ~              ~     -0.88%              ~     +2.39%
Div64SmallNegDivisor                       ~            ~        ~            ~              ~          ~              ~     +0.35%
Div64SmallNegDividend                      ~            ~        ~            ~              ~     -0.84%              ~     +3.57%
Div64SmallNegBoth                          ~            ~        ~            ~              ~     -0.86%              ~     +3.55%
Div64Unsigned                              ~            ~        ~            ~              ~          ~              ~     -0.11%
Div64                                      ~            ~        ~            ~              ~          ~              ~     +0.11%
Div64NegDivisor                            ~            ~        ~            ~              ~     -1.29%              ~          ~
Div64NegDividend                           ~            ~        ~            ~              ~     -1.44%              ~          ~
Div64NegBoth                               ~            ~        ~            ~              ~          ~              ~     +0.28%
Mod64UnsignedSmall                         ~            ~        ~            ~              ~     +0.48%              ~     +0.93%
Mod64Small                                 ~            ~        ~            ~              ~          ~              ~          ~
Mod64SmallNegDivisor                       ~            ~        ~            ~              ~          ~              ~     +1.44%
Mod64SmallNegDividend                      ~            ~        ~            ~              ~     +0.22%              ~     +1.37%
Mod64SmallNegBoth                          ~            ~        ~            ~              ~          ~              ~     -2.22%
Mod64Unsigned                              ~            ~        ~            ~              ~     -0.95%              ~     +0.11%
Mod64                                      ~            ~        ~            ~              ~          ~              ~          ~
Mod64NegDivisor                            ~            ~        ~            ~              ~          ~              ~     -0.02%
Mod64NegDividend                           ~            ~        ~            ~              ~          ~              ~          ~
Mod64NegBoth                               ~            ~        ~            ~              ~          ~              ~     -0.02%
MulconstI32/3                              ~            ~        ~      -25.00%              ~          ~              ~    +47.37%
MulconstI32/5                              ~            ~        ~      +33.28%              ~          ~              ~    +32.21%
MulconstI32/12                             ~            ~        ~       -2.13%              ~          ~              ~     -0.02%
MulconstI32/120                            ~            ~        ~       +2.93%              ~          ~              ~     -0.03%
MulconstI32/-120                           ~            ~        ~       -2.17%              ~          ~              ~     -0.03%
MulconstI32/65537                          ~            ~        ~            ~              ~          ~              ~     +0.03%
MulconstI32/65538                          ~            ~        ~            ~              ~    -33.38%              ~     +0.04%
MulconstI64/3                              ~            ~        ~      +33.35%              ~     -0.37%              ~     -0.13%
MulconstI64/5                              ~            ~        ~      -25.00%              ~     -0.34%              ~          ~
MulconstI64/12                             ~            ~        ~       +2.13%              ~    +11.62%              ~     +2.30%
MulconstI64/120                            ~            ~        ~       -1.98%              ~          ~              ~          ~
MulconstI64/-120                           ~            ~        ~       +0.75%              ~          ~              ~          ~
MulconstI64/65537                          ~            ~        ~            ~              ~     +5.61%              ~          ~
MulconstI64/65538                          ~            ~        ~            ~              ~     +5.25%              ~          ~
MulconstU32/3                              ~       +0.81%        ~      +33.39%              ~    +77.92%              ~    -32.31%
MulconstU32/5                              ~            ~        ~      -24.97%              ~    +77.92%              ~    -24.47%
MulconstU32/12                             ~            ~        ~       +2.06%              ~          ~              ~     +0.03%
MulconstU32/120                            ~            ~        ~       -2.74%              ~          ~              ~     +0.03%
MulconstU32/65537                          ~            ~        ~            ~              ~          ~              ~     +0.03%
MulconstU32/65538                          ~            ~        ~            ~              ~    -33.42%              ~     -0.03%
MulconstU64/3                              ~            ~        ~      +33.33%              ~     -0.28%              ~     +1.22%
MulconstU64/5                              ~            ~        ~      -25.00%              ~          ~              ~     -0.64%
MulconstU64/12                             ~            ~        ~       +2.30%              ~    +11.59%              ~     +0.14%
MulconstU64/120                            ~            ~        ~       -2.82%              ~          ~              ~     +0.04%
MulconstU64/65537                          ~       +0.37%        ~            ~              ~     +5.58%              ~          ~
MulconstU64/65538                          ~            ~        ~            ~              ~     +5.16%              ~          ~
ShiftArithmeticRight                       ~            ~        ~            ~              ~    -10.81%              ~     +0.31%
Switch8Predictable                   +14.69%            ~        ~            ~              ~    -24.85%              ~          ~
Switch8Unpredictable                       ~       -0.58%   -3.80%            ~              ~    -11.78%              ~     -0.79%
Switch32Predictable                  -10.33%      +17.89%        ~            ~              ~     +5.76%              ~          ~
Switch32Unpredictable                 -3.15%       +1.19%   +9.42%            ~              ~    -10.30%         -5.09%     +0.44%
SwitchStringPredictable              +70.88%      +20.48%        ~            ~              ~     +2.39%              ~     +0.31%
SwitchStringUnpredictable                  ~       +3.91%   -5.06%       -0.98%              ~     +0.61%         +2.03%          ~
SwitchTypePredictable               +146.58%       -1.10%        ~      -12.45%              ~     -0.46%         -3.81%          ~
SwitchTypeUnpredictable               +0.46%       -0.83%        ~       +4.18%              ~     +0.43%              ~     +0.62%
SwitchInterfaceTypePredictable       -13.41%      -10.13%  +11.03%            ~              ~     -4.38%              ~     +0.75%
SwitchInterfaceTypeUnpredictable      -6.37%       -2.14%        ~       -3.21%              ~     -4.20%              ~     +1.08%

Fixes #63110.
Fixes #75954.

Change-Id: I55a876f08c6c14f419ce1a8cbba2eaae6c6efbf0
Reviewed-on: https://go-review.googlesource.com/c/go/+/714160
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Russ Cox <rsc@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-10-29 18:49:40 -07:00
Jorropo
24af441437 cmd/compile: rewrite proved multiplies by 0 or 1 into CondSelect
Updates #76056

Change-Id: I64fe631ab381c74f902f877392530d7cc91860ab
Reviewed-on: https://go-review.googlesource.com/c/go/+/715044
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-10-28 07:51:50 -07:00
Jorropo
77dc138030 cmd/compile: teach prove about unsigned rounding-up divide
Change-Id: Ia7b5242c723f83ba85d12e4ca64a19fbbd126016
Reviewed-on: https://go-review.googlesource.com/c/go/+/714622
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2025-10-27 19:08:00 -07:00
Youlin Feng
519ae514ab cmd/compile: eliminate bound check for slices of the same length
If two slices start out with the same length and decrease in length by
the same amount on each round of the loop (or in the if block), then
we think their length are always equal.

For example:

if len(a) != len(b) {
	return
}
for len(a) >= 4 {
	a = a[4:]
	b = b[4:] // proved here, omit boundary check
}
if len(a) == len(b) { // proved here
	//...
}

Or, change 'for' to 'if':

if len(a) != len(b) {
	return
}
if len(a) >= 4 {
	a = a[4:]
	b = b[4:]
}
if len(a) == len(b) { // proved here
	//...
}

Fixes #75144

Change-Id: I4e5902a02b5cf8fdc122715a7dbd2fb5e9a8f5dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/699155
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
2025-10-15 12:34:48 -07:00
David Chase
1caa95acfa cmd/compile: enhance prove to deal with double-offset IsInBounds checks
For chunked iterations (useful for, but not exclusive to,
SIMD calculations) it is common to see the combination of
```
for ; i <= len(m)-4; i += 4 {
```
and
```
r0, r1, r2, r3 := m[i], m[i+1], m[i+2], m[i+3]
``

Prove did not handle the case of len-offset1 vs index+offset2
checking, but this change fixes this.  There may be other
similar cases yet to handle -- this worked for the chunked
loops for simd, as well as a handful in std.

Cherry-picked from the dev.simd branch. This CL is not
necessarily SIMD specific. Apply early to reduce risk.

Change-Id: I3785df83028d517e5e5763206653b34b2befd3d0
Reviewed-on: https://go-review.googlesource.com/c/go/+/700696
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/708859
Reviewed-by: David Chase <drchase@google.com>
2025-10-03 12:30:29 -07:00
David Chase
ec70d19023 cmd/compile: rewrite to elide Slicemask from len==c>0 slicing
This might have been something that prove could be educated
into figuring out, but this also works, and it also helps
prove downstream.

Adjusted the prove test, because this change moved a message.

Cherry-picked from the dev.simd branch. This CL is not
necessarily SIMD specific. Apply early to reduce risk.

Change-Id: I5eabe639eff5db9cd9766a6a8666fdb4973829cb
Reviewed-on: https://go-review.googlesource.com/c/go/+/697715
Commit-Queue: David Chase <drchase@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Bypass: David Chase <drchase@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/708858
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
2025-10-03 12:30:21 -07:00
Jorropo
9fcb87c352 cmd/compile: teach prove about len's & cap's max based on the element size
Change-Id: I88056fada1ff488c199fce54cf737dbdd091214d
Reviewed-on: https://go-review.googlesource.com/c/go/+/695095
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2025-08-13 07:21:20 -07:00
Jorropo
8cd85e602a cmd/compile: check domination of loop return in both controls
Fixes #74473

Change-Id: I72ff6b95955ae9407271508aa80f230dcf1b6c74
Reviewed-on: https://go-review.googlesource.com/c/go/+/685816
Reviewed-by: Mark Freeman <mark@golang.org>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2025-07-30 07:31:18 -07:00
Keith Randall
f703dc5bef cmd/compile: add missing StringLen rule in prove
(StringLen (StringMake _ x)) == x, just like the rules we
currently have for slices.

This helps propagate string length knowledge to places which need it.

Change-Id: Ifdcf6d1f2d430c1c4bbac32e0ea74c188eae998e
Reviewed-on: https://go-review.googlesource.com/c/go/+/682777
Reviewed-by: Daniel Morsing <daniel.morsing@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Jorropo <jorropo.pgm@gmail.com>
2025-07-24 16:06:14 -07:00
Jorropo
f32cf8e4b0 cmd/compile: learn transitive proofs for safe unsigned subs
I've split this into it's own CL to make git bisect more effective.

Change-Id: I436ff21a3e2362b3924de25a458534eb9947e013
Reviewed-on: https://go-review.googlesource.com/c/go/+/685821
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
2025-07-24 13:49:07 -07:00
Jorropo
d574856482 cmd/compile: learn transitive proofs for safe negative signed adds
I've split this into it's own CL to make git bisect more effective.

Change-Id: Ib2c6dbc82fb04f50f2d17fbe6626c9fc322fb478
Reviewed-on: https://go-review.googlesource.com/c/go/+/685820
Auto-Submit: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2025-07-24 13:49:03 -07:00
Jorropo
1a72920f09 cmd/compile: learn transitive proofs for safe positive signed adds
I've split this into it's own CL to make git bisect more effective.

Change-Id: I3fbb42ec7d29169a29f7f55ef2c188317512f532
Reviewed-on: https://go-review.googlesource.com/c/go/+/685819
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2025-07-24 13:48:59 -07:00
Jorropo
e5f202bb60 cmd/compile: learn transitive proofs for safe unsigned adds
I've split this into it's own CL to make git bisect more effective.

Change-Id: Iaab5f0bd2ad51e86ced8c6b8fbd371eb75eeef14
Reviewed-on: https://go-review.googlesource.com/c/go/+/685815
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Mark Freeman <mark@golang.org>
2025-07-24 13:48:55 -07:00
Jorropo
554a3c51dc cmd/compile: use min & max builtins to assert constant bounds in prove's tests
I've originally used |= and &= to setup assumptions exploitable by the
operation under test but theses have multiple issues making it poor
for this usecase:
- &= does not pass the minimum value as-is, rather always set it to 0
- |= rounds up the max value to a number of the same length with all ones set
- I've never implemented them to work with negative signed numbers

Change-Id: Ie43c576fb10393e69d6f989b048823daa02b1df8
Reviewed-on: https://go-review.googlesource.com/c/go/+/656160
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
2025-03-11 19:51:59 -07:00
Jorropo
d2842229fc cmd/compile: compute min's & max's limits from argument's limits inside flowLimit
Updates #68857

Change-Id: Ied07e656bba42f3b1b5f9b9f5442806aa2e7959b
Reviewed-on: https://go-review.googlesource.com/c/go/+/656157
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Jorropo <jorropo.pgm@gmail.com>
2025-03-11 19:51:31 -07:00
Jakub Ciolek
b7c9cdd53c cmd/compile: establish limits of bool to uint8 conversions
Improves bound check elimination for:

func arrayLargeEnough(b bool, a [2]int64) int64 {
    c := byte(0)
    if b {
        c = 1
    }

    // this bound check gets elided
    return a[c]
}

We also detect never true branches like:

func cCanOnlyBe0or1(b bool) byte {
    var c byte
    if b {
        c = 1
    }
    // this statement can never be true so we can elide it
    if c == 2 {
        c = 3
    }

    return c
}

Hits a few times:

crypto/internal/sysrand
crypto/internal/sysrand.Read 357 -> 349  (-2.24%)

testing
testing.(*F).Fuzz.func1.1 837 -> 828  (-1.08%)

image/png
image/png.(*Encoder).Encode 1735 -> 1733  (-0.12%)

vendor/golang.org/x/crypto/cryptobyte
vendor/golang.org/x/crypto/cryptobyte.(*Builder).callContinuation 187 -> 185  (-1.07%)

crypto/internal/sysrand [cmd/compile]
crypto/internal/sysrand.Read 357 -> 349  (-2.24%)

go/parser
go/parser.(*parser).parseType 463 -> 457  (-1.30%)
go/parser.(*parser).embeddedElem 633 -> 626  (-1.11%)
go/parser.(*parser).parseFuncDecl 917 -> 914  (-0.33%)
go/parser.(*parser).parseDotsType 393 -> 391  (-0.51%)
go/parser.(*parser).error 1061 -> 1054  (-0.66%)
go/parser.(*parser).parseTypeName 537 -> 532  (-0.93%)
go/parser.(*parser).parseParamDecl 1478 -> 1451  (-1.83%)
go/parser.(*parser).parseFuncTypeOrLit 498 -> 495  (-0.60%)
go/parser.(*parser).parseValue 375 -> 371  (-1.07%)
go/parser.(*parser).parseElementList 594 -> 593  (-0.17%)
go/parser.(*parser).parseResult 593 -> 583  (-1.69%)
go/parser.(*parser).parseElement 506 -> 504  (-0.40%)
go/parser.(*parser).parseImportSpec 1110 -> 1108  (-0.18%)
go/parser.(*parser).parseStructType 741 -> 735  (-0.81%)
go/parser.(*parser).parseTypeSpec 1054 -> 1048  (-0.57%)
go/parser.(*parser).parseIdentList 625 -> 623  (-0.32%)
go/parser.(*parser).parseOperand 1221 -> 1199  (-1.80%)
go/parser.(*parser).parseIndexOrSliceOrInstance 2713 -> 2694  (-0.70%)
go/parser.(*parser).parseSwitchStmt 1458 -> 1447  (-0.75%)
go/parser.(*parser).parseArrayFieldOrTypeInstance 1865 -> 1861  (-0.21%)
go/parser.(*parser).parseExpr 307 -> 305  (-0.65%)
go/parser.(*parser).parseSelector 427 -> 425  (-0.47%)
go/parser.(*parser).parseTypeInstance 1433 -> 1420  (-0.91%)
go/parser.(*parser).parseCaseClause 629 -> 626  (-0.48%)
go/parser.(*parser).parseParameterList 4212 -> 4189  (-0.55%)
go/parser.(*parser).parsePointerType 393 -> 391  (-0.51%)
go/parser.(*parser).parseFuncType 465 -> 463  (-0.43%)
go/parser.(*parser).parseTypeAssertion 559 -> 557  (-0.36%)
go/parser.(*parser).parseSimpleStmt 2443 -> 2388  (-2.25%)
go/parser.(*parser).parseCallOrConversion 1093 -> 1087  (-0.55%)
go/parser.(*parser).parseForStmt 2168 -> 2159  (-0.42%)
go/parser.(*parser).embeddedTerm 657 -> 649  (-1.22%)
go/parser.(*parser).parseCommClause 1509 -> 1501  (-0.53%)

cmd/internal/objfile
cmd/internal/objfile.(*goobjFile).symbols 5299 -> 5274  (-0.47%)

net
net.initConfVal 378 -> 374  (-1.06%)
net.(*conf).hostLookupOrder 269 -> 267  (-0.74%)
net.(*conf).addrLookupOrder 261 -> 255  (-2.30%)

cmd/internal/obj/loong64
cmd/internal/obj/loong64.(*ctxt0).oplook 1829 -> 1813  (-0.87%)

cmd/internal/obj/mips
cmd/internal/obj/mips.(*ctxt0).oplook 1428 -> 1400  (-1.96%)

go/types
go/types.(*typeWriter).signature 605 -> 601  (-0.66%)
go/types.(*Checker).instantiateSignature 1469 -> 1467  (-0.14%)

go/parser [cmd/compile]
go/parser.(*parser).parseSwitchStmt 1458 -> 1447  (-0.75%)
go/parser.(*parser).parseDotsType 393 -> 391  (-0.51%)
go/parser.(*parser).embeddedElem 633 -> 626  (-1.11%)
go/parser.(*parser).parseTypeAssertion 559 -> 557  (-0.36%)
go/parser.(*parser).parseCommClause 1509 -> 1501  (-0.53%)
go/parser.(*parser).parseCaseClause 629 -> 626  (-0.48%)
go/parser.(*parser).parseImportSpec 1110 -> 1108  (-0.18%)
go/parser.(*parser).parseTypeSpec 1054 -> 1048  (-0.57%)
go/parser.(*parser).parseElementList 594 -> 593  (-0.17%)
go/parser.(*parser).parseParamDecl 1478 -> 1451  (-1.83%)
go/parser.(*parser).parseType 463 -> 457  (-1.30%)
go/parser.(*parser).parseSimpleStmt 2443 -> 2388  (-2.25%)
go/parser.(*parser).parseIdentList 625 -> 623  (-0.32%)
go/parser.(*parser).parseTypeInstance 1433 -> 1420  (-0.91%)
go/parser.(*parser).parseResult 593 -> 583  (-1.69%)
go/parser.(*parser).parseValue 375 -> 371  (-1.07%)
go/parser.(*parser).parseFuncDecl 917 -> 914  (-0.33%)
go/parser.(*parser).error 1061 -> 1054  (-0.66%)
go/parser.(*parser).parseElement 506 -> 504  (-0.40%)
go/parser.(*parser).parseFuncType 465 -> 463  (-0.43%)
go/parser.(*parser).parsePointerType 393 -> 391  (-0.51%)
go/parser.(*parser).parseTypeName 537 -> 532  (-0.93%)
go/parser.(*parser).parseExpr 307 -> 305  (-0.65%)
go/parser.(*parser).parseFuncTypeOrLit 498 -> 495  (-0.60%)
go/parser.(*parser).parseStructType 741 -> 735  (-0.81%)
go/parser.(*parser).parseOperand 1221 -> 1199  (-1.80%)
go/parser.(*parser).parseIndexOrSliceOrInstance 2713 -> 2694  (-0.70%)
go/parser.(*parser).parseForStmt 2168 -> 2159  (-0.42%)
go/parser.(*parser).parseParameterList 4212 -> 4189  (-0.55%)
go/parser.(*parser).parseArrayFieldOrTypeInstance 1865 -> 1861  (-0.21%)
go/parser.(*parser).parseSelector 427 -> 425  (-0.47%)
go/parser.(*parser).parseCallOrConversion 1093 -> 1087  (-0.55%)
go/parser.(*parser).embeddedTerm 657 -> 649  (-1.22%)

crypto/tls
crypto/tls.(*Conn).clientHandshake 3430 -> 3421  (-0.26%)

cmd/internal/obj/mips [cmd/compile]
cmd/internal/obj/mips.(*ctxt0).oplook 1428 -> 1400  (-1.96%)

cmd/internal/obj/loong64 [cmd/compile]
cmd/internal/obj/loong64.(*ctxt0).oplook 1829 -> 1813  (-0.87%)

cmd/compile/internal/types2
cmd/compile/internal/types2.(*typeWriter).signature 605 -> 601  (-0.66%)
cmd/compile/internal/types2.(*Checker).infer 10646 -> 10614  (-0.30%)
cmd/compile/internal/types2.(*Checker).instantiateSignature 1567 -> 1561  (-0.38%)

cmd/compile/internal/types2 [cmd/compile]
cmd/compile/internal/types2.(*Checker).instantiateSignature 1567 -> 1561  (-0.38%)
cmd/compile/internal/types2.(*typeWriter).signature 605 -> 601  (-0.66%)
cmd/compile/internal/types2.(*Checker).infer 10718 -> 10654  (-0.60%)

cmd/vendor/golang.org/x/arch/s390x/s390xasm
cmd/vendor/golang.org/x/arch/s390x/s390xasm.GoSyntax 36778 -> 36682  (-0.26%)

net/http
net/http.(*Client).do 4202 -> 4170  (-0.76%)
net/http.(*http2clientStream).writeRequest 3692 -> 3686  (-0.16%)

cmd/vendor/github.com/ianlancetaylor/demangle
cmd/vendor/github.com/ianlancetaylor/demangle.(*rustState).genericArgs 466 -> 463  (-0.64%)

cmd/compile/internal/devirtualize
cmd/compile/internal/devirtualize.ProfileGuided.func1 1364 -> 1357  (-0.51%)

cmd/compile/internal/inline/interleaved
cmd/compile/internal/inline/interleaved.DevirtualizeAndInlinePackage.func2 533 -> 526  (-1.31%)

cmd/compile/internal/devirtualize [cmd/compile]
cmd/compile/internal/devirtualize.ProfileGuided.func1 1343 -> 1332  (-0.82%)

cmd/compile/internal/inline/interleaved [cmd/compile]
cmd/compile/internal/inline/interleaved.DevirtualizeAndInlinePackage.func2 533 -> 526  (-1.31%)

cmd/link/internal/ld
cmd/link/internal/ld.mustLinkExternal 2739 -> 2674  (-2.37%)

cmd/compile/internal/ssa
cmd/compile/internal/ssa.(*poset).Ordered 391 -> 389  (-0.51%)
cmd/compile/internal/ssa.(*poset).Equal 318 -> 313  (-1.57%)
cmd/compile/internal/ssa.(*poset).Undo 1842 -> 1832  (-0.54%)
cmd/compile/internal/ssa.(*expandState).decomposeAsNecessary 4587 -> 4555  (-0.70%)
cmd/compile/internal/ssa.(*poset).OrderedOrEqual 390 -> 389  (-0.26%)
cmd/compile/internal/ssa.(*poset).NonEqual 613 -> 606  (-1.14%)

cmd/compile/internal/ssa [cmd/compile]
cmd/compile/internal/ssa.(*poset).OrderedOrEqual 368 -> 365  (-0.82%)
cmd/compile/internal/ssa.(*poset).Equal 318 -> 313  (-1.57%)
cmd/compile/internal/ssa.(*expandState).decomposeAsNecessary 4952 -> 4938  (-0.28%)
cmd/compile/internal/ssa.(*poset).NonEqual 613 -> 606  (-1.14%)
cmd/compile/internal/ssa.(*poset).SetEqual 2533 -> 2505  (-1.11%)
cmd/compile/internal/ssa.(*poset).SetNonEqual 785 -> 777  (-1.02%)
cmd/compile/internal/ssa.(*poset).Ordered 370 -> 366  (-1.08%)

cmd/compile/internal/gc [cmd/compile]
cmd/compile/internal/gc.Main.DevirtualizeAndInlinePackage.func2 492 -> 489  (-0.61%)

file                                                    before   after    Δ       %
crypto/internal/sysrand.s                               1553     1545     -8      -0.515%
internal/zstd.s                                         49179    49190    +11     +0.022%
testing.s                                               115197   115188   -9      -0.008%
image/png.s                                             36109    36107    -2      -0.006%
vendor/golang.org/x/crypto/cryptobyte.s                 30980    30978    -2      -0.006%
crypto/internal/sysrand [cmd/compile].s                 1553     1545     -8      -0.515%
go/parser.s                                             112638   112354   -284    -0.252%
cmd/internal/objfile.s                                  49994    49969    -25     -0.050%
net.s                                                   299558   299546   -12     -0.004%
cmd/internal/obj/loong64.s                              71651    71635    -16     -0.022%
cmd/internal/obj/mips.s                                 59681    59653    -28     -0.047%
go/types.s                                              558839   558833   -6      -0.001%
cmd/compile/internal/types.s                            71305    71306    +1      +0.001%
go/parser [cmd/compile].s                               112749   112465   -284    -0.252%
crypto/tls.s                                            388859   388850   -9      -0.002%
cmd/internal/obj/mips [cmd/compile].s                   59792    59764    -28     -0.047%
cmd/internal/obj/loong64 [cmd/compile].s                71762    71746    -16     -0.022%
cmd/compile/internal/types2.s                           540608   540566   -42     -0.008%
cmd/compile/internal/types2 [cmd/compile].s             577428   577354   -74     -0.013%
cmd/vendor/golang.org/x/arch/s390x/s390xasm.s           267664   267568   -96     -0.036%
net/http.s                                              620704   620666   -38     -0.006%
cmd/vendor/github.com/ianlancetaylor/demangle.s         299991   299988   -3      -0.001%
cmd/compile/internal/devirtualize.s                     21452    21445    -7      -0.033%
cmd/compile/internal/inline/interleaved.s               8358     8351     -7      -0.084%
cmd/compile/internal/devirtualize [cmd/compile].s       20994    20983    -11     -0.052%
cmd/compile/internal/inline/interleaved [cmd/compile].s 8328     8321     -7      -0.084%
cmd/link/internal/ld.s                                  641802   641737   -65     -0.010%
cmd/compile/internal/ssa.s                              3552939  3552957  +18     +0.001%
cmd/compile/internal/ssa [cmd/compile].s                3752191  3752197  +6      +0.000%
cmd/compile/internal/ssagen.s                           405780   405786   +6      +0.001%
cmd/compile/internal/ssagen [cmd/compile].s             434472   434496   +24     +0.006%
cmd/compile/internal/gc [cmd/compile].s                 38499    38496    -3      -0.008%
total                                                   36185267 36184243 -1024   -0.003%

Change-Id: I867222b0f907b29d32b2676e55c6b5789ec56511
Reviewed-on: https://go-review.googlesource.com/c/go/+/642716
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2025-02-05 09:04:25 -08:00
Keith Randall
4dcbb00be2 cmd/compile: teach prove about min/max phi operations
If there is a phi that is computing the minimum of its two inputs,
then we know the result of the phi is smaller than or equal to both
of its inputs. Similarly for maxiumum (although max seems less useful).

This pattern happens for the case

  n := copy(a, b)

n is the minimum of len(a) and len(b), so with this optimization we
know both n <= len(a) and n <= len(b). That extra information is
helpful for subsequent slicing of a or b.

Fixes #16833

Change-Id: Ib4238fd1edae0f2940f62a5516a6b363bbe7928c
Reviewed-on: https://go-review.googlesource.com/c/go/+/622240
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
2024-10-29 16:46:48 +00:00
Jorropo
820f58a27f cmd/compile: compute Negation's limits from argument's limits
Change-Id: I2e4d74a86faa95321e847a061e06c3efff7f20df
Reviewed-on: https://go-review.googlesource.com/c/go/+/605775
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-09-03 21:12:20 +00:00
Jorropo
2f3165973f cmd/compile: compute Complement's limits from argument's limits
I was not sure this was correct so I exhaustively checked all possibilities:
https://go.dev/play/p/hjmCLm4Iagz
https://go.dev/play/p/R9RuRGKwCbN

Change-Id: I85f053df825a4d77f978de42f8a1fcaf4b881def
Reviewed-on: https://go-review.googlesource.com/c/go/+/605696
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
2024-09-03 21:12:13 +00:00
Jorropo
4f2c0e5d08 cmd/compile: compute Trunc's limits from argument's limits
Change-Id: I419faa781db085b98ea25008ca127d0317fb34e1
Reviewed-on: https://go-review.googlesource.com/c/go/+/605695
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Carlos Amedee <carlos@golang.org>
2024-09-03 21:12:00 +00:00
Jorropo
68c431e89f cmd/compile: propagate unsigned limits for Div and Mod if arguments are positive
I didn't implemented negative limits since prove is most useful for BCE which
should never be negative in the first place.

Change-Id: I302ee462cdc20bd4edff0618f7e49ff66fc2a007
Reviewed-on: https://go-review.googlesource.com/c/go/+/605136
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2024-09-03 21:11:49 +00:00
Jorropo
e23ebec90d cmd/compile: compute Divu's limits from argument's limits
Change-Id: Id522bde5bba627d9cdc8c3d8e907bdc168e5b13c
Reviewed-on: https://go-review.googlesource.com/c/go/+/605157
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
2024-09-03 17:13:20 +00:00
Jorropo
194fa2eb6c cmd/compile: compute Modu's maximum limits from argument's limits
addLocalFacts loop already ft.update which sets up limits correctly, but doing this in flowLimit help us since other values might depend on this limit.

Updates #68857

We could improve this further:
- remove mod alltogheter when we can prove a < b.
- we could do more adhoc computation in flowLimit to set umax and umin tighter

Change-Id: I5184913577b6a51a07cb53a6e6b73552a982de0b
Reviewed-on: https://go-review.googlesource.com/c/go/+/605156
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-09-03 17:13:06 +00:00
Jorropo
57df33814a cmd/compile: compute OR's maximum limits from argument's limits
Change-Id: I6902c405cab7bd573f6a721a6ca7c783713ea39a
Reviewed-on: https://go-review.googlesource.com/c/go/+/604456
Reviewed-by: Keith Randall <khr@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2024-09-03 17:12:58 +00:00
Jorropo
49621cc311 cmd/compile: compute XOR's limits from argument's limits
This help to optimize code like this:

  func f(buckets *[512]bucket, v value) {
    a, b := v.computeSomething()
    // assume a and b are proved < 512
    b := &buckets[a ^ b] // pick a random bucket
    b.store(v)
  }

Change-Id: I1acf702f5a8137f9ded49081b4703922879b0288
Reviewed-on: https://go-review.googlesource.com/c/go/+/604455
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-09-03 17:12:49 +00:00
Jorropo
f49fe2955d cmd/compile: compute bits.TrailingZeros*'s limits from argument's limits
y := bits.TrailingZeros(x)
if y > bits.Len(x.umax)-1 {
 then must always be true 1 << y > x.umax which is impossible
}

Change-Id: Iab4fce1c2ef828bee3a8a4a977cbadb5f9333136
Reviewed-on: https://go-review.googlesource.com/c/go/+/603996
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@golang.org>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
2024-09-03 16:38:49 +00:00
Jorropo
0c7523ff59 cmd/compile: compute bits.Len*'s limits from argument's limits
Change-Id: Ie3c7e5eaba6a9a29389018625c4b784d07c6f173
Reviewed-on: https://go-review.googlesource.com/c/go/+/603537
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-09-03 16:38:16 +00:00
khr@golang.org
f32ec41df5 cmd/compile: reorganize prove pass domain relation table
Move some code from when we learn that we take a branch, to when
we learn that a boolean is true or false. It is more consistent
this way (and may lead to a few more cases where we can derive
useful relations).

Change-Id: Iea7b2d6740e10c9c71c4b1546881f501da81cd21
Reviewed-on: https://go-review.googlesource.com/c/go/+/599098
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2024-08-07 16:08:03 +00:00
khr@golang.org
5925cd3d15 cmd/compile: handle boolean and pointer relations
The constant lattice for these types is pretty simple.
We no longer need the old-style facts table, as the ordering
table now has all that information.

Change-Id: If0e118c27a4de8e9bfd727b78942185c2eb50c4b
Reviewed-on: https://go-review.googlesource.com/c/go/+/599097
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2024-08-07 16:07:55 +00:00
khr@golang.org
a4a130f6d0 cmd/compile: propagate constant ranges through multiplies and shifts
Fixes #40704
Fixes #66826

Change-Id: Ia9c356e29b2ed6f2e3bc6e5eb9304cd4dccb4263
Reviewed-on: https://go-review.googlesource.com/c/go/+/599256
Reviewed-by: Michael Knyszek <mknyszek@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
2024-08-07 16:07:42 +00:00
khr@golang.org
3b96eebcbd cmd/compile: rewrite the constant parts of the prove pass
Handles a lot more cases where constant ranges can eliminate
various (mostly bounds failure) paths.

Fixes #66826
Fixes #66692
Fixes #48213
Update #57959

TODO: remove constant logic from poset code, no longer needed.

Change-Id: Id196436fcd8a0c84c7d59c04f93bd92e26a0fd7e
Reviewed-on: https://go-review.googlesource.com/c/go/+/599096
Reviewed-by: David Chase <drchase@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2024-08-07 16:07:33 +00:00
Jorropo
bbd0bc22ea cmd/compile: improve integer comparisons with numeric bounds
This do:
- Fold always false or always true comparisons for ints and uint.
- Reduce < and <= where the true set is only one value to == with such value.

Change-Id: Ie9e3f70efd1845bef62db56543f051a50ad2532e
Reviewed-on: https://go-review.googlesource.com/c/go/+/555135
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2024-01-23 00:02:36 +00:00
Dmitri Shuralyov
b2fd76ab8d test: migrate remaining files to go:build syntax
Most of the test cases in the test directory use the new go:build syntax
already. Convert the rest. In general, try to place the build constraint
line below the test directive comment in more places.

For #41184.
For #60268.

Change-Id: I11c41a0642a8a26dc2eda1406da908645bbc005b
Cq-Include-Trybots: luci.golang.try:gotip-linux-386-longtest,gotip-linux-amd64-longtest,gotip-windows-amd64-longtest
Reviewed-on: https://go-review.googlesource.com/c/go/+/536236
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
2023-10-19 23:33:25 +00:00
Cuong Manh Le
63a08e61bd cmd/compile: teach prove about bitwise OR operation
For now, only apply the rule if either of arguments are constants. That
would catch a lot of real user code, without slowing down the compiler
with code generated for string comparison (experience in CL 410336).

Updates #57959
Fixes #45928

Change-Id: Ie2e830d6d0d71cda3947818b22c2775bd94f7971
Reviewed-on: https://go-review.googlesource.com/c/go/+/483359
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2023-04-10 17:13:41 +00:00
ruinan
9be533a8ee cmd/compile: get more bounds info from logic operators in prove pass
Currently, the prove pass can get knowledge from some specific logic
operators only before the CFG is explored, which means that the bounds
information of the branch will be ignored.

This CL updates the facts table by the logic operators in every
branch. Combined with the branch information, this will be helpful for
BCE in some circumstances.

Fixes #57243

Change-Id: I0bd164f1b47804ccfc37879abe9788740b016fd5
Reviewed-on: https://go-review.googlesource.com/c/go/+/419555
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Eric Fang <eric.fang@arm.com>
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2023-04-07 10:09:11 +00:00
Michael Munday
85d54a7667 cmd/compile: use zero constants in comparisons where possible
Some integer comparisons with 1 and -1 can be rewritten as comparisons
with 0. For example, x < 1 is equivalent to x <= 0. This is an
advantageous transformation on riscv64 because comparisons with zero
do not require a constant to be loaded into a register. Other
architectures will likely benefit too and the transformation is
relatively benign on architectures that do not benefit.

Change-Id: I2ce9821dd7605a660eb71d76e83a61f9bae1bf25
Reviewed-on: https://go-review.googlesource.com/c/go/+/350831
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Run-TryBot: Michael Munday <mike.munday@lowrisc.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
2023-02-27 21:38:30 +00:00
Keith Randall
a6ddb15f8f Revert "cmd/compile: teach prove about bitwise OR operation"
This reverts commit 3680b5e9c4.

Reason for revert: causes long compile times on certain functions. See issue #57959

Change-Id: Ie9e881ca8abbc79a46de2bfeaed0b9d6c416ed42
Reviewed-on: https://go-review.googlesource.com/c/go/+/463295
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
2023-01-24 17:58:12 +00:00
Jorropo
35755d772f cmd/compile: teach prove about unsigned division, modulus and rsh
Fixes: #57077
Change-Id: Icffcac42e28622eadecdba26e3cd7ceca6c4aacc
Reviewed-on: https://go-review.googlesource.com/c/go/+/455095
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2023-01-23 18:35:41 +00:00
Keith Randall
0156b797e6 cmd/compile: recognize when the result of append has a constant length
Fixes a performance regression due to CL 418554.

Fixes #56440

Change-Id: I6ff152e9b83084756363f49ee6b0844a7a284880
Reviewed-on: https://go-review.googlesource.com/c/go/+/445875
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2022-10-27 17:09:50 +00:00
Wayne Zuo
3680b5e9c4 cmd/compile: teach prove about bitwise OR operation
Fixes #45928.

Change-Id: Ifbb0effbca4ab7c0eb56069fee40edb564553c35
Reviewed-on: https://go-review.googlesource.com/c/go/+/410336
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-08-31 09:35:45 +00:00
Wayne Zuo
d2e0587f77 cmd/compile: derive relation between x+delta and x in prove
If x+delta cannot overflow/underflow, we can derive:
  x+delta < x if delta<0 (this CL included)
  x+delta > x if delta>0 (this CL not included due to
  a recursive stack overflow)

Remove 95 bounds checks during ./make.bat

Fixes #51622

Change-Id: I60d9bd84c5d7e81bbf808508afd09be596644f09
Reviewed-on: https://go-review.googlesource.com/c/go/+/406175
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-08-31 09:35:10 +00:00
Keith Randall
661146bc0b cmd/compile: don't use OFORUNTIL when implementing range loops
We don't need this special loop construct anymore now that we do
conservative GC scanning of the top of stack. Rewrite instead to a simple
pointer increment on every iteration. This leads to having a potential
past-the-end pointer at the end of the last iteration, but that value
immediately goes dead after the loop condition fails, and the past-the-end
pointer is never live across any call.

This simplifies and speeds up loops.

R=go1.20

TODO: actually delete all support for OFORUNTIL. It is now never generated,
but code to handle it (e.g. in ssagen) is still around.

TODO: in "for _, x := range" loops, we could get rid of the index
altogether and use a "pointer to the last element" reference to determine
when the loop is complete.

Fixes #53409

Change-Id: Ifc141600ff898a8bc6a75f793e575f8862679ba1
Reviewed-on: https://go-review.googlesource.com/c/go/+/414876
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-08-18 17:32:44 +00:00
Wayne Zuo
1efe38750a cmd/compile: teach prove about and operation
For this code:
z &= 63
_ = x<<z | x>>(64-z)
Now can prove 'x<<z' in bound. In ppc64 lowering pass, it will not
produce an extra '(ANDconst <typ.Int64> [63] z)' causing
codegen/rotate.go failed. Just remove the type check in rewrite rules
as the workaround.

Removes 32 bounds checks during make.bat.

Fixes #52563.

Change-Id: I14ed2c093ff5638dfea7de9bc7649c0f756dd71a
Reviewed-on: https://go-review.googlesource.com/c/go/+/404315
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
Auto-Submit: Keith Randall <khr@golang.org>
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-05-08 20:10:06 +00:00