Commit graph

81 commits

Author SHA1 Message Date
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
John Bampton
6ba4a300d8 docs: fix spelling
Change-Id: Ib689e5793d9cb372e759c4f34af71f004010c822
GitHub-Last-Rev: d63798388e
GitHub-Pull-Request: golang/go#44259
Reviewed-on: https://go-review.googlesource.com/c/go/+/291949
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Trust: Robert Griesemer <gri@golang.org>
2021-02-24 04:11:43 +00:00
Cuong Manh Le
5e804ba17d cmd/compile: use transitive relations for slice len/cap in poset
Currently, we keep track of slice len by mapping from slice ID to
len/cap SSA value. However, slice len/cap can have multiple SSA values,
so when updating fact table for slice len/cap, we only update in one
place.

Instead, we can take advantage of the transitive relations provided by
poset. So all duplicated slice lens are set as equal to one another.
When updating fact table for one, that fact will be reflected to all
others. The same mechanism is applied for slice cap.

Removes 15 bounds checks from std/cmd.

Fixes #42603

Change-Id: I32c07968824cc33765b1e441b3ae2c4b5f5997c3
Reviewed-on: https://go-review.googlesource.com/c/go/+/273670
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2021-02-23 05:01:04 +00:00
Cholerae Hu
a6755fc0de cmd/compile: check indirect connection between if block and phi block in addLocalInductiveFacts
CL 244579 added guard clauses to prevent a faulty state that was
possible under the incorrect logic of the uniquePred loop in
addLocalInductiveFacts. That faulty state was still making the
intended optimization, but not for the correct reason.
Removing the faulty state also removed the overly permissive application
of the optimization, and therefore made these two tests fail.
We disabled the tests of this optimization in CL 244579 to allow us to
quickly apply the fix in the CL. This CL now corrects the logic of the
uniquePred loop in order to apply the optimization correctly.

The comment above the uniquePred loop says that it will follow unique
predecessors until it reaches a join point. Without updating the child
node on each iteration, it cannot follow the chain of unique
predecessors more than one step. Adding the update to the child node
on each iteration of the loop allows the logic to follow the chain of
unique predecessors until reaching a join point (because a non-unique
predecessor will signify a join point).

Updates #40502.

Change-Id: I23d8367046a2ab3ce4be969631f9ba15dc533e6c
Reviewed-on: https://go-review.googlesource.com/c/go/+/246157
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Trust: Dmitri Shuralyov <dmitshur@golang.org>
2020-11-07 07:33:23 +00:00
Cholerae Hu
7f86080476 cmd/compile: don't addLocalInductiveFacts if there is no direct edge from if block to phi block
Currently in addLocalInductiveFacts, we only check whether
direct edge from if block to phi block exists. If not, the
following logic will treat the phi block as the first successor,
which is wrong.

This patch makes prove pass more conservative, so we disable
some cases in test/prove.go. We will do some optimization in
the following CL and enable these cases then.

Fixes #40367.

Change-Id: I27cf0248f3a82312a6f7dabe11c79a1a34cf5412
Reviewed-on: https://go-review.googlesource.com/c/go/+/244579
Reviewed-by: Zach Jones <zachj1@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-07-30 17:23:11 +00:00
Keith Randall
2cb10d42b7 cmd/compile: in prove, zero right shifts of positive int by #bits - 1
Taking over Zach's CL 212277. Just cleaned up and added a test.

For a positive, signed integer, an arithmetic right shift of count
(bit-width - 1) equals zero. e.g. int64(22) >> 63 -> 0. This CL makes
prove replace these right shifts with a zero-valued constant.

These shifts may arise in source code explicitly, but can also be
created by the generic rewrite of signed division by a power of 2.
// Signed divide by power of 2.
// n / c =       n >> log(c) if n >= 0
//       = (n+c-1) >> log(c) if n < 0
// We conditionally add c-1 by adding n>>63>>(64-log(c))
	(first shift signed, second shift unsigned).
(Div64 <t> n (Const64 [c])) && isPowerOfTwo(c) ->
  (Rsh64x64
    (Add64 <t> n (Rsh64Ux64 <t>
    	(Rsh64x64 <t> n (Const64 <typ.UInt64> [63]))
	(Const64 <typ.UInt64> [64-log2(c)])))
    (Const64 <typ.UInt64> [log2(c)]))

If n is known to be positive, this rewrite includes an extra Add and 2
extra Rsh. This CL will allow prove to replace one of the extra Rsh with
a 0. That replacement then allows lateopt to remove all the unneccesary
fixups from the generic rewrite.

There is a rewrite rule to handle this case directly:
(Div64 n (Const64 [c])) && isNonNegative(n) && isPowerOfTwo(c) ->
	(Rsh64Ux64 n (Const64 <typ.UInt64> [log2(c)]))
But this implementation of isNonNegative really only handles constants
and a few special operations like len/cap. The division could be
handled if the factsTable version of isNonNegative were available.
Unfortunately, the first opt pass happens before prove even has a
chance to deduce the numerator is non-negative, so the generic rewrite
has already fired and created the extra Ops discussed above.

Fixes #36159

By Printf count, this zeroes 137 right shifts when building std and cmd.

Change-Id: Iab486910ac9d7cfb86ace2835456002732b384a2
Reviewed-on: https://go-review.googlesource.com/c/go/+/232857
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2020-05-11 16:23:52 +00:00
Michael Munday
cb74dcc172 cmd/compile: remove Greater* and Geq* generic integer ops
The generic Greater and Geq ops can always be replaced with the Less and
Leq ops. This CL therefore removes them. This simplifies the compiler since
it reduces the number of operations that need handling in both code and in
rewrite rules. This will be especially true when adding control flow
optimizations such as the integer-in-range optimizations in CL 165998.

Change-Id: If0648b2b19998ac1bddccbf251283f3be4ec3040
Reviewed-on: https://go-review.googlesource.com/c/go/+/220417
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2020-02-26 13:11:53 +00:00
zdjones
3c56eb4083 cmd/compile: make poset use sufficient conditions for OrderedOrEqual
When assessing whether A <= B, the poset's OrderedOrEqual has a passing
condition which permits A <= B, but is not sufficient to infer that A <= B.
This CL removes that incorrect passing condition.

Having identified that A and B are in the poset, the method will report that
A <= B if any of these three conditions are true:
 (1) A and B are the same node in the poset.
 	- This means we know that A == B.
 (2) There is a directed path, strict or not, from A -> B
 	- This means we know that, at least, A <= B, but A < B is possible.
 (3) There is a directed path from B -> A, AND that path has no strict edges.
 	- This means we know that B <= A, but do not know that B < A.

In condition (3), we do not have enough information to say that A <= B, rather
we only know that B == A (which satisfies A <= B) is possible. The way I
understand it, a strict edge shows a known, strictly-ordered relation (<) but
the lack of a strict edge does not show the lack of a strictly-ordered relation.

The difference is highlighted by the example in #34802, where a bounds check is
incorrectly removed by prove, such that negative indexes into a slice
succeed:

	n := make([]int, 1)
	for i := -1; i <= 0; i++ {
	    fmt.Printf("i is %d\n", i)
	    n[i] = 1  // No Bounds check, program runs, assignment to n[-1] succeeds!!
	}

When prove is checking the negative/failed branch from the bounds check at n[i],
in the signed domain we learn (0 > i || i >= len(n)). Because prove can't learn
the OR condition, we check whether we know that i is non-negative so we can
learn something, namely that i >= len(n). Prove uses the poset to check whether
we know that i is non-negative.  At this point the poset holds the following
relations as a directed graph:

	-1 <= i <= 0
	-1 < 0

In poset.OrderedOrEqual, we are testing for 0 <= i. In this case, condition (3)
above is true because there is a non-strict path from i -> 0, and that path
does NOT have any strict edges. Because this condition is true, the poset
reports to prove that i is known to be >= 0. Knowing, incorrectly, that i >= 0,
prove learns from the failed bounds check that i >= len(n) in the signed domain.

When the slice, n, was created, prove learned that len(n) == 1. Because i is
also the induction variable for the loop, upon entering the loop, prove previously
learned that i is in [-1,0]. So when prove attempts to learn from the failed
bounds check, it finds the new fact, i > len(n), unsatisfiable given that it
previously learned that i <= 0 and len(n) = 1.

Fixes #34802

Change-Id: I235f4224bef97700c3aa5c01edcc595eb9f13afc
Reviewed-on: https://go-review.googlesource.com/c/go/+/200759
Run-TryBot: Zach Jones <zachj1@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Giovanni Bajo <rasky@develer.com>
Reviewed-by: Keith Randall <khr@golang.org>
2019-10-12 09:17:14 +00:00
David Chase
adc4d2cc2d cmd/compile: run deadcode before nilcheck for better statement relocation
Nilcheck would move statements from NilCheck values to others that
turned out were already dead, which leads to lost statements.  Better
to eliminate the dead code first.

One "error" is removed from test/prove.go because the code is
actually dead, and the additional deadcode pass removes it before
prove can run.

Change-Id: If75926ca1acbb59c7ab9c8ef14d60a02a0a94f8b
Reviewed-on: https://go-review.googlesource.com/c/go/+/198479
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2019-10-03 21:12:13 +00:00
Giovanni Bajo
87e2b34f7b cmd/compile: in prove, learn facts from OpSliceMake
Now that OpSliceMake is called by runtime.makeslice callers,
prove can see and record the actual length and cap of each
slice being constructed.

This small patch is enough to remove 260 additional bound checks
from cmd+std.

Thanks to Martin Möhrmann for pointing me to CL141822 that
I had missed.

Updates #24660

Change-Id: I14556850f285392051f3f07d13b456b608b64eb9
Reviewed-on: https://go-review.googlesource.com/c/go/+/196784
Run-TryBot: Giovanni Bajo <rasky@develer.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
2019-09-26 18:27:38 +00:00
zdjones
69ff0ba798 cmd/compile: handle sign/zero extensions in prove, via update method
Array accesses with index types smaller than the machine word size may
involve a sign or zero extension of the index value before bounds
checking. Currently, this defeats prove because the facts about the
original index value don't flow through the sign/zero extension.

This CL fixes this by looking back through value-preserving sign/zero
extensions when adding facts via Update and, where appropriate, applying
the same facts using the pre-extension value. This fix is enhanced by
also looking back through value-preserving extensions within
ft.isNonNegative to infer whether the extended value is known to be
non-negative. Without this additional isNonNegative enhancement, this
logic is rendered significantly less effective by the limitation
discussed in the next paragraph.

In Update, the application of facts to pre-extension values is limited
to cases where the domain of the new fact is consistent with the type of
the pre-extension value. There may be cases where this cross-domain
passing of facts is valid, but distinguishing them from the invalid
cases is difficult for me to reason about and to implement.
Assessing which cases to allow requires details about the context and
inferences behind the fact being applied which are not available
within Update. Additional difficulty arises from the fact that the SSA
does not curently differentiate extensions added by the compiler for
indexing operations, extensions added by the compiler for implicit
conversions, or explicit extensions from the source.

Examples of some cases that would need to be filtered correctly for
cross-domain facts:

(1) A uint8 is zero-extended to int for indexing (a value-preserving
zeroExt). When, if ever, can signed domain facts learned about the int be
applied to the uint8?

(2) An int8 is sign-extended to int16 (value-preserving) for an equality
comparison. Equality comparison facts are currently always learned in both
the signed and unsigned domains. When, if ever, can the unsigned facts
learned about the int16, from the int16 != int16 comparison, be applied
to the original int8?

This is an alternative to CL 122695 and CL 174309. Compared to CL 122695,
this CL differs in that the facts added about the pre-extension value will
pass through the Update method, where additional inferences are processed
(e.g. fence-post implications, see #29964). CL 174309 is limited to bounds
checks, so is narrower in application, and makes the code harder to read.

Fixes #26292.
Fixes #29964.
Fixes #15074

Removes 238 bounds checks from std/cmd.

Change-Id: I1f87c32ee672bfb8be397b27eab7a4c2f304893f
Reviewed-on: https://go-review.googlesource.com/c/go/+/174704
Run-TryBot: Zach Jones <zachj1@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Giovanni Bajo <rasky@develer.com>
2019-08-27 16:46:34 +00:00