]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.link] all: merge branch 'master' into dev.link
authorCherry Zhang <cherryyz@google.com>
Thu, 11 Jun 2020 20:49:19 +0000 (16:49 -0400)
committerCherry Zhang <cherryyz@google.com>
Thu, 11 Jun 2020 20:49:19 +0000 (16:49 -0400)
Change-Id: I446db56b20ef2189e23e225a91a17736c1d11e4c

71 files changed:
.gitattributes
AUTHORS
CONTRIBUTORS
api/go1.15.txt [new file with mode: 0644]
api/next.txt
doc/go1.10.html
doc/go1.15.html
src/all.bat
src/clean.bat
src/cmd/addr2line/addr2line_test.go
src/cmd/asm/internal/asm/testdata/arm64enc.s
src/cmd/cgo/doc.go
src/cmd/compile/fmt_test.go
src/cmd/compile/fmtmap_test.go
src/cmd/compile/internal/arm/ssa.go
src/cmd/compile/internal/gc/esc.go
src/cmd/compile/internal/ssa/compile.go
src/cmd/compile/internal/ssa/cse.go
src/cmd/compile/internal/ssa/gen/ARM.rules
src/cmd/compile/internal/ssa/gen/ARMOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewriteARM.go
src/cmd/compile/internal/ssa/rewriteCond_test.go
src/cmd/compile/internal/ssa/tuple.go [new file with mode: 0644]
src/cmd/dist/test.go
src/cmd/go/go_test.go
src/cmd/go/internal/web/http.go
src/cmd/go/internal/work/gc.go
src/cmd/go/proxy_test.go
src/cmd/go/script_test.go
src/cmd/go/testdata/script/README
src/cmd/go/testdata/script/build_trimpath.txt
src/cmd/go/testdata/script/goroot_executable.txt
src/cmd/go/testdata/script/mod_convert_dep.txt
src/cmd/go/testdata/script/mod_get_too_many_redirects.txt [new file with mode: 0644]
src/cmd/internal/moddeps/moddeps_test.go
src/cmd/internal/obj/arm64/asm7.go
src/cmd/internal/objabi/util.go
src/cmd/link/dwarf_test.go
src/cmd/link/internal/loader/loader.go
src/cmd/objdump/objdump_test.go
src/crypto/tls/common.go
src/crypto/tls/handshake_client.go
src/crypto/tls/handshake_client_test.go
src/crypto/tls/handshake_client_tls13.go
src/crypto/x509/x509.go
src/go/internal/srcimporter/srcimporter.go
src/go/types/api.go
src/go/types/check.go
src/go/types/resolver.go
src/html/template/html.go
src/internal/poll/fd_unix.go
src/make.bat
src/net/http/request.go
src/net/http/server.go
src/os/file_unix.go
src/os/removeall_at.go
src/os/signal/internal/pty/pty.go
src/os/signal/signal_cgo_test.go
src/race.bat
src/run.bat
src/runtime/cgo_sigaction.go
src/runtime/debugcall.go
src/runtime/malloc.go
src/runtime/mgcmark.go
src/runtime/mstats.go
src/runtime/mwbbuf.go
src/runtime/symtab.go
test/codegen/comparisons.go
test/fixedbugs/issue39472.go [new file with mode: 0644]
test/winbatch.go

index bcea0290f4c8d9197fc7d7c055a8055126278078..cabbb1732c418125f9c773ce7a28ba34f2708554 100644 (file)
@@ -1,16 +1,16 @@
 # Treat all files in the Go repo as binary, with no git magic updating
-# line endings. Windows users contributing to Go will need to use a
-# modern version of git and editors capable of LF line endings.
+# line endings. This produces predictable results in different environments.
+#
+# Windows users contributing to Go will need to use a modern version
+# of git and editors capable of LF line endings.
+#
+# Windows .bat files are known to have multiple bugs when run with LF
+# endings, and so they are checked in with CRLF endings, with a test
+# in test/winbatch.go to catch problems. (See golang.org/issue/37791.)
 #
 # We'll prevent accidental CRLF line endings from entering the repo
-# via the git-review gofmt checks.
+# via the git-codereview gofmt checks and tests.
 #
-# See golang.org/issue/9281
+# See golang.org/issue/9281.
 
 * -text
-
-# The only exception is Windows files that must absolutely be CRLF or
-# might not work. Batch files are known to have multiple bugs when run
-# with LF endings. See golang.org/issue/37791 for more information.
-
-*.bat text eol=crlf
diff --git a/AUTHORS b/AUTHORS
index 69e35a13ae2bb1feaa7c4e2413e8c531ced55e86..80c79feb33495110ab4a9011040d63e974d11c8d 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -1397,6 +1397,7 @@ Upthere, Inc.
 Uriel Mangado <uriel@berlinblue.org>
 Vadim Grek <vadimprog@gmail.com>
 Vadim Vygonets <unixdj@gmail.com>
+Vee Zhang <veezhang@126.com> <vveezhang@gmail.com>
 Vendasta
 Veselkov Konstantin <kostozyb@gmail.com>
 Victor Vrantchan <vrancean+github@gmail.com>
index 934834fc797033120277eacfef6359a1407e1178..6b6ee094157660d87813ae43a6b2458ceb1705ca 100644 (file)
@@ -2195,6 +2195,7 @@ Vadim Grek <vadimprog@gmail.com>
 Vadim Vygonets <unixdj@gmail.com>
 Val Polouchkine <vpolouch@justin.tv>
 Valentin Vidic <vvidic@valentin-vidic.from.hr>
+Vee Zhang <veezhang@126.com> <vveezhang@gmail.com>
 Vega Garcia Luis Alfonso <vegacom@gmail.com>
 Venil Noronha <veniln@vmware.com>
 Veselkov Konstantin <kostozyb@gmail.com>
diff --git a/api/go1.15.txt b/api/go1.15.txt
new file mode 100644 (file)
index 0000000..b51837c
--- /dev/null
@@ -0,0 +1,132 @@
+pkg bufio, var ErrBadReadCount error
+pkg crypto, method (Hash) String() string
+pkg crypto/ecdsa, func SignASN1(io.Reader, *PrivateKey, []uint8) ([]uint8, error)
+pkg crypto/ecdsa, func VerifyASN1(*PublicKey, []uint8, []uint8) bool
+pkg crypto/ecdsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool
+pkg crypto/ecdsa, method (*PublicKey) Equal(crypto.PublicKey) bool
+pkg crypto/ed25519, method (PrivateKey) Equal(crypto.PrivateKey) bool
+pkg crypto/ed25519, method (PublicKey) Equal(crypto.PublicKey) bool
+pkg crypto/elliptic, func MarshalCompressed(Curve, *big.Int, *big.Int) []uint8
+pkg crypto/elliptic, func UnmarshalCompressed(Curve, []uint8) (*big.Int, *big.Int)
+pkg crypto/rsa, method (*PrivateKey) Equal(crypto.PrivateKey) bool
+pkg crypto/rsa, method (*PublicKey) Equal(crypto.PublicKey) bool
+pkg crypto/tls, method (*Dialer) Dial(string, string) (net.Conn, error)
+pkg crypto/tls, method (*Dialer) DialContext(context.Context, string, string) (net.Conn, error)
+pkg crypto/tls, method (ClientAuthType) String() string
+pkg crypto/tls, method (CurveID) String() string
+pkg crypto/tls, method (SignatureScheme) String() string
+pkg crypto/tls, type Config struct, VerifyConnection func(ConnectionState) error
+pkg crypto/tls, type Dialer struct
+pkg crypto/tls, type Dialer struct, Config *Config
+pkg crypto/tls, type Dialer struct, NetDialer *net.Dialer
+pkg crypto/x509, func CreateRevocationList(io.Reader, *RevocationList, *Certificate, crypto.Signer) ([]uint8, error)
+pkg crypto/x509, type RevocationList struct
+pkg crypto/x509, type RevocationList struct, ExtraExtensions []pkix.Extension
+pkg crypto/x509, type RevocationList struct, NextUpdate time.Time
+pkg crypto/x509, type RevocationList struct, Number *big.Int
+pkg crypto/x509, type RevocationList struct, RevokedCertificates []pkix.RevokedCertificate
+pkg crypto/x509, type RevocationList struct, SignatureAlgorithm SignatureAlgorithm
+pkg crypto/x509, type RevocationList struct, ThisUpdate time.Time
+pkg database/sql, method (*DB) SetConnMaxIdleTime(time.Duration)
+pkg database/sql, method (*Row) Err() error
+pkg database/sql, type DBStats struct, MaxIdleTimeClosed int64
+pkg database/sql/driver, type Validator interface { IsValid }
+pkg database/sql/driver, type Validator interface, IsValid() bool
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_APPCONTAINER = 4096
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_APPCONTAINER ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE = 64
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY = 128
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_GUARD_CF = 16384
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_GUARD_CF ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA = 32
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_BIND = 2048
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_BIND ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION = 512
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_ISOLATION ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_SEH = 1024
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NO_SEH ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NX_COMPAT = 256
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_NX_COMPAT ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE = 32768
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE ideal-int
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER = 8192
+pkg debug/pe, const IMAGE_DLLCHARACTERISTICS_WDM_DRIVER ideal-int
+pkg debug/pe, const IMAGE_FILE_32BIT_MACHINE = 256
+pkg debug/pe, const IMAGE_FILE_32BIT_MACHINE ideal-int
+pkg debug/pe, const IMAGE_FILE_AGGRESIVE_WS_TRIM = 16
+pkg debug/pe, const IMAGE_FILE_AGGRESIVE_WS_TRIM ideal-int
+pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_HI = 32768
+pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_HI ideal-int
+pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_LO = 128
+pkg debug/pe, const IMAGE_FILE_BYTES_REVERSED_LO ideal-int
+pkg debug/pe, const IMAGE_FILE_DEBUG_STRIPPED = 512
+pkg debug/pe, const IMAGE_FILE_DEBUG_STRIPPED ideal-int
+pkg debug/pe, const IMAGE_FILE_DLL = 8192
+pkg debug/pe, const IMAGE_FILE_DLL ideal-int
+pkg debug/pe, const IMAGE_FILE_EXECUTABLE_IMAGE = 2
+pkg debug/pe, const IMAGE_FILE_EXECUTABLE_IMAGE ideal-int
+pkg debug/pe, const IMAGE_FILE_LARGE_ADDRESS_AWARE = 32
+pkg debug/pe, const IMAGE_FILE_LARGE_ADDRESS_AWARE ideal-int
+pkg debug/pe, const IMAGE_FILE_LINE_NUMS_STRIPPED = 4
+pkg debug/pe, const IMAGE_FILE_LINE_NUMS_STRIPPED ideal-int
+pkg debug/pe, const IMAGE_FILE_LOCAL_SYMS_STRIPPED = 8
+pkg debug/pe, const IMAGE_FILE_LOCAL_SYMS_STRIPPED ideal-int
+pkg debug/pe, const IMAGE_FILE_NET_RUN_FROM_SWAP = 2048
+pkg debug/pe, const IMAGE_FILE_NET_RUN_FROM_SWAP ideal-int
+pkg debug/pe, const IMAGE_FILE_RELOCS_STRIPPED = 1
+pkg debug/pe, const IMAGE_FILE_RELOCS_STRIPPED ideal-int
+pkg debug/pe, const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 1024
+pkg debug/pe, const IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP ideal-int
+pkg debug/pe, const IMAGE_FILE_SYSTEM = 4096
+pkg debug/pe, const IMAGE_FILE_SYSTEM ideal-int
+pkg debug/pe, const IMAGE_FILE_UP_SYSTEM_ONLY = 16384
+pkg debug/pe, const IMAGE_FILE_UP_SYSTEM_ONLY ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_APPLICATION = 10
+pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_APPLICATION ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER = 11
+pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_ROM = 13
+pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_ROM ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER = 12
+pkg debug/pe, const IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE = 1
+pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8
+pkg debug/pe, const IMAGE_SUBSYSTEM_NATIVE_WINDOWS ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_OS2_CUI = 5
+pkg debug/pe, const IMAGE_SUBSYSTEM_OS2_CUI ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_POSIX_CUI = 7
+pkg debug/pe, const IMAGE_SUBSYSTEM_POSIX_CUI ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_UNKNOWN = 0
+pkg debug/pe, const IMAGE_SUBSYSTEM_UNKNOWN ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION = 16
+pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9
+pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CUI = 3
+pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_CUI ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
+pkg debug/pe, const IMAGE_SUBSYSTEM_WINDOWS_GUI ideal-int
+pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX = 14
+pkg debug/pe, const IMAGE_SUBSYSTEM_XBOX ideal-int
+pkg go/printer, const StdFormat = 16
+pkg go/printer, const StdFormat Mode
+pkg math/big, method (*Int) FillBytes([]uint8) []uint8
+pkg net, method (*Resolver) LookupIP(context.Context, string, string) ([]IP, error)
+pkg net/url, method (*URL) EscapedFragment() string
+pkg net/url, method (*URL) Redacted() string
+pkg net/url, type URL struct, RawFragment string
+pkg os, method (*File) ReadFrom(io.Reader) (int64, error)
+pkg os, var ErrDeadlineExceeded error
+pkg regexp, method (*Regexp) SubexpIndex(string) int
+pkg strconv, func FormatComplex(complex128, uint8, int, int) string
+pkg strconv, func ParseComplex(string, int) (complex128, error)
+pkg sync, method (*Map) LoadAndDelete(interface{}) (interface{}, bool)
+pkg testing, method (*B) TempDir() string
+pkg testing, method (*T) Deadline() (time.Time, bool)
+pkg testing, method (*T) TempDir() string
+pkg testing, type TB interface, TempDir() string
+pkg time, method (*Ticker) Reset(Duration)
index 442c29a4164245d91bdd69f7823c96db89210275..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,3 +0,0 @@
-pkg testing, method (*T) Deadline() (time.Time, bool)
-pkg time, method (*Ticker) Reset(Duration)
-pkg sync, method (*Map) LoadAndDelete(interface{}) (interface{}, bool)
index 41db36ab1ec5920395c197948b9015c9e94bf68b..853f874ded4445056fa13052b5237ee49dc63568 100644 (file)
@@ -30,7 +30,7 @@ adds <a href="#test">caching of successful test results</a>,
 runs <a href="#test-vet">vet automatically during tests</a>,
 and
 permits <a href="#cgo">passing string values directly between Go and C using cgo</a>.
-A new <a href="#cgo">compiler option whitelist</a> may cause
+A new <a href="#cgo">hard-coded set of safe compiler options</a> may cause
 unexpected <a href="https://golang.org/s/invalidflag"><code>invalid
 flag</code></a> errors in code that built successfully with older
 releases.
@@ -267,7 +267,7 @@ and the <a href="/cmd/test2json/">test2json documentation</a>.
 
 <p>
 Options specified by cgo using <code>#cgo CFLAGS</code> and the like
-are now checked against a whitelist of permitted options.
+are now checked against a list of permitted options.
 This closes a security hole in which a downloaded package uses
 compiler options like
 <span style="white-space: nowrap"><code>-fplugin</code></span>
index 492cac0b09f11a09b9ff0981588f4719f4b68675..dd25b27c5f679a6f35b4b880513e70f56c74c698 100644 (file)
@@ -55,6 +55,13 @@ Do not send CLs removing the interior tags from such phrases.
   on Windows.
 </p>
 
+<p><!-- CL 227003 -->
+  The <code>-race</code> and <code>-msan</code> flags now always
+  enable <code>-d=checkptr</code>, which checks uses
+  of <code>unsafe.Pointer</code>. This was previously the case on all
+  OSes except Windows.
+</p>
+
 <p><!-- CL 211139 -->
   Go-built DLLs no longer cause the process to exit when it receives a
   signal (such as Ctrl-C at a terminal).
@@ -211,10 +218,24 @@ Do not send CLs removing the interior tags from such phrases.
 
 <h2 id="runtime">Runtime</h2>
 
-<p><!-- CL 232862 -->
-  Go now retries system calls that return <code>EINTR</code>. This
-  became more common in Go 1.14 with the addition of asynchronous
-  preemption, but is now handled transparently.
+<p><!-- CL 221779 -->
+  If <code>panic</code> is invoked with a value whose type is derived from any
+  of: <code>bool</code>, <code>complex64</code>, <code>complex128</code>, <code>float32</code>, <code>float64</code>,
+  <code>int</code>, <code>int8</code>, <code>int16</code>, <code>int32</code>, <code>int64</code>, <code>string</code>,
+  <code>uint</code>, <code>uint8</code>, <code>uint16</code>, <code>uint32</code>, <code>uint64</code>, <code>uintptr</code>,
+  then the value will be printed, instead of just its address.
+  Previously, this was only true for values of exactly these types.
+</p>
+
+<p><!-- CL 228900 -->
+  On a Unix system, if the <code>kill</code> command
+  or <code>kill</code> system call is used to send
+  a <code>SIGSEGV</code>, <code>SIGBUS</code>,
+  or <code>SIGFPE</code> signal to a Go program, and if the signal
+  is not being handled via
+  <a href="/pkg/os/signal/#Notify"><code>os/signal.Notify</code></a>,
+  the Go program will now reliably crash with a stack trace.
+  In earlier releases the behavior was unpredictable.
 </p>
 
 <p><!-- CL 221182, CL 229998 -->
@@ -222,8 +243,14 @@ Do not send CLs removing the interior tags from such phrases.
   counts, and has lower worst-case latency.
 </p>
 
-<p>
-TODO
+<p><!-- CL 216401 -->
+  Converting a small integer value into an interface value no longer
+  causes allocation.
+</p>
+
+<p><!-- CL 216818 -->
+  Non-blocking receives on closed channels now perform as well as
+  non-blocking receives on open channels.
 </p>
 
 <h2 id="compiler">Compiler</h2>
@@ -245,6 +272,15 @@ TODO
   aggressively eliminating unused type metadata.
 </p>
 
+<p><!-- CL 219357, CL 231600 -->
+  The toolchain now mitigates
+  <a href="https://www.intel.com/content/www/us/en/support/articles/000055650/processors.html">Intel
+  CPU erratum SKX102</a> on <code>GOARCH=amd64</code> by aligning
+  functions to 32 byte boundaries and padding jump instructions. While
+  this padding increases binary sizes, this is more than made up for
+  by the binary size improvements mentioned above.
+</p>
+
 <p><!-- CL 222661 -->
   Go 1.15 adds a <code>-spectre</code> flag to both the
   compiler and the assembler, to allow enabling Spectre mitigations.
@@ -253,6 +289,19 @@ TODO
   See the <a href="https://github.com/golang/go/wiki/Spectre">Spectre wiki page</a> for details.
 </p>
 
+<p><!-- CL 228578 -->
+  The compiler now rejects <code>//go:</code> compiler directives that
+  have no meaning for the declaration they are applied to with a
+  "misplaced compiler directive" error. Such misapplied directives
+  were broken before, but were silently ignored by the compiler.
+</p>
+
+<p><!-- CL 206658, CL 205066 -->
+  The compiler's <code>-json</code> optimization logging now reports
+  large (>= 128 byte) copies and includes explanations of escape
+  analysis decisions.
+</p>
+
 <h2 id="linker">Linker</h2>
 
 <p>
@@ -283,6 +332,14 @@ TODO
   improvements expected in future releases.
 </p>
 
+<h2 id="objdump">Objdump</h2>
+
+<p><!-- CL 225459 -->
+  The <a href="/cmd/objdump/">objdump</a> tool now supports
+  disassembling in GNU assembler syntax with the <code>-gnu</code>
+  flag.
+</p>
+
 <h2 id="library">Core library</h2>
 
 <h3 id="time/tzdata">New embedded tzdata package</h3>
@@ -299,10 +356,6 @@ TODO
   Either approach increases the size of the program by about 800 KB.
 </p>
 
-<p>
-TODO
-</p>
-
 <h3 id="cgo">Cgo</h3>
 
 <p><!-- CL 235817 -->
@@ -321,10 +374,6 @@ TODO
   in mind.
 </p>
 
-<p>
-TODO
-</p>
-
 <dl id="debug/pe"><dt><a href="/pkg/debug/pe/">debug/pe</a></dt>
   <dd>
     <p><!-- CL 222637 -->
@@ -336,10 +385,53 @@ TODO
   </dd>
 </dl><!-- debug/pe -->
 
+<dl id="crypto"><dt><a href="/pkg/crypto/">crypto</a></dt>
+  <dd>
+    <p><!-- CL 231417, CL 225460 -->
+      The <code>PrivateKey</code> and <code>PublicKey</code> types in the
+      <a href="/pkg/crypto/rsa"><code>crypto/rsa</code></a>,
+      <a href="/pkg/crypto/ecdsa"><code>crypto/ecdsa</code></a>, and
+      <a href="/pkg/crypto/ed25519"><code>crypto/ed25519</code></a> packages
+      now have an <code>Equal</code> method to compare keys for equivalence
+      or to make type-safe interfaces for public keys. The method signature
+      is compatible with
+      <a href="https://pkg.go.dev/github.com/google/go-cmp/cmp#Equal"><code>go-cmp</code>'s
+      definition of equality</a>.
+    </p>
+
+    <p><!-- CL 224937 -->
+      <a href="/pkg/crypto/#Hash"><code>Hash</code></a> now implements
+      <a href="/pkg/fmt/#Stringer"><code>fmt.Stringer</code></a>.
+    </p>
+  </dd>
+</dl><!-- crypto -->
+
+<dl id="crypto/ecdsa"><dt><a href="/pkg/crypto/ecdsa/">crypto/ecdsa</a></dt>
+  <dd>
+    <p><!-- CL 217940 -->
+      The new <a href="/pkg/crypto/ecdsa/#SignASN1"><code>SignASN1</code></a>
+      and <a href="/pkg/crypto/ecdsa/#VerifyASN1"><code>VerifyASN1</code></a>
+      functions allow generating and verifying ECDSA signatures in the standard
+      ASN.1 DER encoding.
+    </p>
+  </dd>
+</dl><!-- crypto/ecdsa -->
+
+<dl id="crypto/elliptic"><dt><a href="/pkg/crypto/elliptic/">crypto/elliptic</a></dt>
+  <dd>
+    <p><!-- CL 202819 -->
+      The new <a href="/pkg/crypto/elliptic/#MarshalCompressed"><code>MarshalCompressed</code></a>
+      and <a href="/pkg/crypto/elliptic/#UnmarshalCompressed"><code>UnmarshalCompressed</code></a>
+      functions allow encoding and decoding NIST elliptic curve points in compressed format.
+    </p>
+  </dd>
+</dl><!-- crypto/elliptic -->
+
 <dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
   <dd>
     <p><!-- CL 226203 -->
-      VerifyPKCS1v15 now rejects invalid short signatures with missing leading zeroes.
+      <a href="/pkg/crypto/rsa/#VerifyPKCS1v15"><code>VerifyPKCS1v15</code></a>
+      now rejects invalid short signatures with missing leading zeroes, according to RFC 8017.
     </p>
   </dd>
 </dl><!-- crypto/rsa -->
@@ -353,21 +445,137 @@ TODO
       <a href="/pkg/crypto/tls/#Dialer.DialContext"><code>DialContext</code></a>
       method permits using a context to both connect and handshake with a TLS server.
     </p>
+
+    <p><!-- CL 229122 -->
+      The new
+      <a href="/pkg/crypto/tls/#Config.VerifyConnection"><code>VerifyConnection</code></a>
+      callback on the <a href="/pkg/crypto/tls/#Config"><code>Config</code></a> type
+      allows custom verification logic for every connection. It has access to the
+      <a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>
+      which includes peer certificates, SCTs, and stapled OCSP responses.
+    </p>
+
+    <p><!-- CL 230679 -->
+      Auto-generated session ticket keys are now automatically rotated every 24 hours,
+      with a lifetime of 7 days, to limit their impact on forward secrecy.
+    </p>
+
+    <p><!-- CL 231317 -->
+      Session ticket lifetimes in TLS 1.2 and earlier, where the session keys
+      are reused for resumed connections, are now limited to 7 days, also to
+      limit their impact on forward secrecy.
+    </p>
+
+    <p><!-- CL 231038 -->
+      The client-side downgrade protection checks specified in RFC 8446 are now
+      enforced. This has the potential to cause connection errors for clients
+      encountering middleboxes that behave like unauthorized downgrade attacks.
+    </p>
+
+    <p><!-- CL 208226 -->
+      <a href="/pkg/crypto/tls/#SignatureScheme"><code>SignatureScheme</code></a>,
+      <a href="/pkg/crypto/tls/#CurveID"><code>CurveID</code></a>, and
+      <a href="/pkg/crypto/tls/#ClientAuthType"><code>ClientAuthType</code></a>
+      now implement <a href="/pkg/fmt/#Stringer"><code>fmt.Stringer</code></a>.
+    </p>
+
+    <p><!-- CL 236737 -->
+      The <a href="/pkg/crypto/tls/#ConnectionState"><code>ConnectionState</code></a>
+      fields <code>OCSPResponse</code> and <code>SignedCertificateTimestamps</code>
+      are now repopulated on client-side resumed connections.
+    </p>
   </dd>
-</dl>
+</dl><!-- crypto/tls -->
 
 <dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
   <dd>
+    <p><!-- CL 231378, CL 231380, CL 231381 -->
+      If either the name on the certificate or the name being verified (with
+      <a href="/pkg/crypto/x509/#VerifyOptions.DNSName"><code>VerifyOptions.DNSName</code></a>
+      or <a href="/pkg/crypto/x509/#Certificate.VerifyHostname"><code>VerifyHostname</code></a>)
+      are invalid, they will now be compared case-insensitively without further
+      processing (without honoring wildcards or stripping trailing dots).
+      Invalid names include those with any characters other than letters,
+      digits, hyphens and underscores, those with empty labels, and names on
+      certificates with trailing dots.
+    </p>
+
+    <p><!-- CL 231379 -->
+      The deprecated, legacy behavior of treating the <code>CommonName</code>
+      field as a hostname when no Subject Alternative Names are present is now
+      disabled by default. It can be temporarily re-enabled by adding the value
+      <code>x509ignoreCN=0</code> to the <code>GODEBUG</code> environment
+      variable. If the <code>CommonName</code> is an invalid hostname, it's
+      always ignored.
+    </p>
+
+    <p><!-- CL 217298 -->
+      The new <a href="/pkg/crypto/x509/#CreateRevocationList"><code>CreateRevocationList</code></a>
+      function and <a href="/pkg/crypto/x509/#RevocationList"><code>RevocationList</code></a> type
+      allow creating RFC 5280-compliant X.509 v2 Certificate Revocation Lists.
+    </p>
+
+    <p><!-- CL 227098 -->
+      <a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
+      now automatically generates the <code>SubjectKeyId</code> if the template
+      is a CA and doesn't explicitly specify one.
+    </p>
+
+    <p><!-- CL 228777 -->
+      <a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
+      now returns an error if the template specifies <code>MaxPathLen</code> but is not a CA.
+    </p>
+
     <p><!-- CL 205237 -->
-      TODO: <a href="https://golang.org/cl/205237">https://golang.org/cl/205237</a>: load roots from colon separated SSL_CERT_DIR in loadSystemRoots
+      On Unix systems other than macOS, the <code>SSL_CERT_DIR</code>
+      environment variable can now be a colon-separated list.
+    </p>
+
+    <p><!-- CL 227037 -->
+      On macOS, binaries are now always linked against
+      <code>Security.framework</code> to extract the system trust roots,
+      regardless of whether cgo is available. The resulting behavior should be
+      more consistent with the OS verifier.
     </p>
   </dd>
 </dl><!-- crypto/x509 -->
 
+<dl id="crypto/x509/pkix"><dt><a href="/pkg/crypto/x509/pkix/">crypto/x509/pkix</a></dt>
+  <dd>
+    <p><!-- CL 229864 -->
+      <a href="/pkg/crypto/x509/pkix/#Name.String"><code>Name.String</code></a>
+      now prints non-standard attributes from
+      <a href="/pkg/crypto/x509/pkix/#Name.Names"><code>Names</code></a> if
+      <a href="/pkg/crypto/x509/pkix/#Name.ExtraNames"><code>ExtraNames</code></a> is empty.
+    </p>
+  </dd>
+</dl><!-- crypto/x509/pkix -->
+
+<dl id="encoding/json"><dt><a href="/pkg/encoding/json/">encoding/json</a></dt>
+  <dd>
+    <p><!-- CL 191783 -->
+      Decoding a JSON array into a slice no longer reuses any existing slice elements,
+      following the rules that the package documentation already stated.
+    </p>
+
+    <p><!-- CL 199837 -->
+      Introduce an internal limit to the maximum depth of nesting when decoding.
+      This reduces the possibility that a deeply nested input could use large quantities
+      of stack memory, or even cause a "goroutine stack exceeds limit" panic.
+    </p>
+  </dd>
+</dl><!-- encoding/json -->
+
 <dl id="encoding/xml"><dt><a href="/pkg/encoding/xml/">encoding/xml</a></dt>
   <dd>
     <p><!-- CL 203417 -->
-      TODO: <a href="https://golang.org/cl/203417">https://golang.org/cl/203417</a>: fix reserved namespace check to be case-insensitive
+      The encoder has always taken care to avoid using namespace prefixes beginning with
+      <code>xml</code>,
+      which are reserved by the XML specification.
+      Now, following the specification more closely,
+      that check is case-insensitive, so that prefixes beginning with
+      <code>XML</code>, <code>XmL</code>,
+      and so on are also avoided.
     </p>
   </dd>
 </dl><!-- encoding/xml -->
@@ -390,7 +598,8 @@ TODO
 <dl id="fmt"><dt><a href="/pkg/fmt/">fmt</a></dt>
   <dd>
     <p><!-- CL 215001 -->
-      TODO: <a href="https://golang.org/cl/215001">https://golang.org/cl/215001</a>: do not remove trailing zeros for %g and %G with #(sharp) flag
+      The printing verbs <code>%#g</code> and <code>%#G</code> now preserve
+      trailing zeros for floating-point values.
     </p>
   </dd>
 </dl><!-- fmt -->
@@ -410,7 +619,8 @@ TODO
 <dl id="math/big"><dt><a href="/pkg/math/big/">math/big</a></dt>
   <dd>
     <p><!-- CL 230397 -->
-      TODO: <a href="https://golang.org/cl/230397">https://golang.org/cl/230397</a>: add (*Int).FillBytes
+      The new <a href="/pkg/math/big/#Int.FillBytes"><code>Int.FillBytes</code></a>
+      method allows serializing to fixed-size pre-allocated byte slices.
     </p>
   </dd>
 </dl><!-- math/big -->
@@ -441,8 +651,10 @@ TODO
 
 <dl id="net/http"><dt><a href="/pkg/net/http/">net/http</a></dt>
   <dd>
-    <p><!-- CL 231418 -->
-      TODO: <a href="https://golang.org/cl/231418">https://golang.org/cl/231418</a>: only support &#34;chunked&#34; in inbound Transfer-Encoding headers
+    <p><!-- CL 231418, CL 231419 -->
+      Parsing is now stricter as a hardening measure against request smuggling attacks:
+      non-ASCII white space is no longer trimmed like SP and HTAB, and support for the
+      "<code>identity</code>" <code>Transfer-Encoding</code> was dropped.
     </p>
   </dd>
 </dl><!-- net/http -->
@@ -457,7 +669,9 @@ TODO
     </p>
 
     <p><!-- CL 224897 -->
-      TODO: <a href="https://golang.org/cl/224897">https://golang.org/cl/224897</a>: make Switching Protocol requests (e.g. Websockets) cancelable
+      When a Switching Protocol (like WebSocket) request handled by
+      <a href="/pkg/net/http/httputil/#ReverseProxy"><code>ReverseProxy</code></a>
+      is canceled, the backend connection is now correctly closed.
     </p>
   </dd>
 </dl>
@@ -506,6 +720,14 @@ TODO
       which <code>Timeout</code> returns <code>true</code> although a
       deadline has not been exceeded.
     </p>
+
+    <p><!-- CL 232862 -->
+      Packages <code>os</code> and <code>net</code> now automatically
+      retry system calls that fail with <code>EINTR</code>. Previously
+      this led to spurious failures, which became more common in Go
+      1.14 with the addition of asynchronous preemption. Now this is
+      handled transparently.
+    </p>
   </dd>
 </dl>
 
@@ -525,7 +747,7 @@ TODO
 <dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
   <dd>
     <p><!-- CL 228902 -->
-      Package reflect now disallows accessing methods of all
+      Package <code>reflect</code> now disallows accessing methods of all
       non-exported fields, whereas previously it allowed accessing
       those of non-exported, embedded fields. Code that relies on the
       previous behavior should be updated to instead access the
@@ -546,26 +768,6 @@ TODO
 
 <dl id="pkg-runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
   <dd>
-    <p><!-- CL 221779 -->
-      If <code>panic</code> is invoked with a value whose type is derived from any
-      of: <code>bool</code>, <code>complex64</code>, <code>complex128</code>, <code>float32</code>, <code>float64</code>,
-      <code>int</code>, <code>int8</code>, <code>int16</code>, <code>int32</code>, <code>int64</code>, <code>string</code>,
-      <code>uint</code>, <code>uint8</code>, <code>uint16</code>, <code>uint32</code>, <code>uint64</code>, <code>uintptr</code>,
-      then the value will be printed, instead of just its address.
-      Previously, this was only true for values of exactly these types.
-    </p>
-
-    <p><!-- CL -->
-      On a Unix system, if the <code>kill</code> command
-      or <code>kill</code> system call is used to send
-      a <code>SIGSEGV</code>, <code>SIGBUS</code>,
-      or <code>SIGFPE</code> signal to a Go program, and if the signal
-      is not being handled via
-      <a href="/pkg/os/signal/#Notify"><code>os/signal.Notify</code></a>,
-      the Go program will now reliably crash with a stack trace.
-      In earlier releases the behavior was unpredictable.
-    </p>
-
     <p><!-- CL 216557 -->
       Several functions, including
       <a href="/pkg/runtime/#ReadMemStats"><code>ReadMemStats</code></a>
@@ -573,16 +775,6 @@ TODO
       <a href="/pkg/runtime/#GoroutineProfile"><code>GoroutineProfile</code></a>,
       no longer block if a garbage collection is in progress.
     </p>
-
-    <p><!-- CL 216401 -->
-      Converting small integer values into an interface value no
-      longer causes allocation.
-    </p>
-
-    <p><!-- CL 216818 -->
-      Non-blocking receives on closed channels now perform as well as
-      non-blocking receives on open channels.
-    </p>
   </dd>
 </dl>
 
index 8bbd6b1b5dae5c0b1b893d0364557c327893965d..ae835d992f318d4440f2d8ffad0769e154e7ecf3 100644 (file)
@@ -1,27 +1,27 @@
-:: Copyright 2012 The Go Authors. All rights reserved.
-:: Use of this source code is governed by a BSD-style
-:: license that can be found in the LICENSE file.
-
-@echo off
-
-setlocal
-
-if exist make.bat goto ok
-echo all.bat must be run from go\src
-:: cannot exit: would kill parent command interpreter
-goto end
-:ok
-
-set OLDPATH=%PATH%
-call make.bat --no-banner --no-local
-if %GOBUILDFAIL%==1 goto end
-call run.bat --no-rebuild --no-local
-if %GOBUILDFAIL%==1 goto end
-:: we must restore %PATH% before running "dist banner" so that the latter
-:: can get the original %PATH% and give suggestion to add %GOROOT%/bin
-:: to %PATH% if necessary.
-set PATH=%OLDPATH%
-"%GOTOOLDIR%/dist" banner
-
-:end
-if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
+:: Copyright 2012 The Go Authors. All rights reserved.\r
+:: Use of this source code is governed by a BSD-style\r
+:: license that can be found in the LICENSE file.\r
+\r
+@echo off\r
+\r
+setlocal\r
+\r
+if exist make.bat goto ok\r
+echo all.bat must be run from go\src\r
+:: cannot exit: would kill parent command interpreter\r
+goto end\r
+:ok\r
+\r
+set OLDPATH=%PATH%\r
+call make.bat --no-banner --no-local\r
+if %GOBUILDFAIL%==1 goto end\r
+call run.bat --no-rebuild --no-local\r
+if %GOBUILDFAIL%==1 goto end\r
+:: we must restore %PATH% before running "dist banner" so that the latter\r
+:: can get the original %PATH% and give suggestion to add %GOROOT%/bin\r
+:: to %PATH% if necessary.\r
+set PATH=%OLDPATH%\r
+"%GOTOOLDIR%/dist" banner\r
+\r
+:end\r
+if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%\r
index 0954dcd67f191f373840769a04562ae7916613a7..c957353d0f10f5edfa1a4e833cb134e801f22820 100644 (file)
@@ -1,32 +1,32 @@
-:: Copyright 2012 The Go Authors. All rights reserved.
-:: Use of this source code is governed by a BSD-style
-:: license that can be found in the LICENSE file.
-
-@echo off
-
-setlocal
-
-set GOBUILDFAIL=0
-
-go tool dist env -w -p >env.bat
-if errorlevel 1 goto fail
-call env.bat
-del env.bat
-echo.
-
-if exist %GOTOOLDIR%\dist.exe goto distok
-echo cannot find %GOTOOLDIR%\dist; nothing to clean
-goto fail
-:distok
-
-"%GOBIN%\go" clean -i std
-"%GOBIN%\go" tool dist clean
-"%GOBIN%\go" clean -i cmd
-
-goto end
-
-:fail
-set GOBUILDFAIL=1
-
-:end
-if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
+:: Copyright 2012 The Go Authors. All rights reserved.\r
+:: Use of this source code is governed by a BSD-style\r
+:: license that can be found in the LICENSE file.\r
+\r
+@echo off\r
+\r
+setlocal\r
+\r
+set GOBUILDFAIL=0\r
+\r
+go tool dist env -w -p >env.bat\r
+if errorlevel 1 goto fail\r
+call env.bat\r
+del env.bat\r
+echo.\r
+\r
+if exist %GOTOOLDIR%\dist.exe goto distok\r
+echo cannot find %GOTOOLDIR%\dist; nothing to clean\r
+goto fail\r
+:distok\r
+\r
+"%GOBIN%\go" clean -i std\r
+"%GOBIN%\go" tool dist clean\r
+"%GOBIN%\go" clean -i cmd\r
+\r
+goto end\r
+\r
+:fail\r
+set GOBUILDFAIL=1\r
+\r
+:end\r
+if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%\r
index 22bf1379bb72147c6ccbf72603e4fc8654356478..578d88e432a8a9313826059f6c181c63d458a359 100644 (file)
@@ -73,19 +73,29 @@ func testAddr2Line(t *testing.T, exepath, addr string) {
        if err != nil {
                t.Fatalf("Stat failed: %v", err)
        }
+       // Debug paths are stored slash-separated, so convert to system-native.
+       srcPath = filepath.FromSlash(srcPath)
        fi2, err := os.Stat(srcPath)
+       if gorootFinal := os.Getenv("GOROOT_FINAL"); gorootFinal != "" && strings.HasPrefix(srcPath, gorootFinal) {
+               if os.IsNotExist(err) || (err == nil && !os.SameFile(fi1, fi2)) {
+                       // srcPath has had GOROOT_FINAL substituted for GOROOT, and it doesn't
+                       // match the actual file. GOROOT probably hasn't been moved to its final
+                       // location yet, so try the original location instead.
+                       fi2, err = os.Stat(runtime.GOROOT() + strings.TrimPrefix(srcPath, gorootFinal))
+               }
+       }
        if err != nil {
                t.Fatalf("Stat failed: %v", err)
        }
        if !os.SameFile(fi1, fi2) {
                t.Fatalf("addr2line_test.go and %s are not same file", srcPath)
        }
-       if srcLineNo != "89" {
-               t.Fatalf("line number = %v; want 89", srcLineNo)
+       if srcLineNo != "99" {
+               t.Fatalf("line number = %v; want 99", srcLineNo)
        }
 }
 
-// This is line 88. The test depends on that.
+// This is line 98. The test depends on that.
 func TestAddr2Line(t *testing.T) {
        testenv.MustHaveGoBuild(t)
 
index a483c731b81224ddf86d51304141bdbf0def59d3..56cf51c3039c4abec896e2c89b2e476921ae1757 100644 (file)
@@ -420,6 +420,7 @@ TEXT asmtest(SB),DUPOK|NOSPLIT,$-8
    UXTBW R2, R6                               // 461c0053
    UXTHW R7, R20                              // f43c0053
    VCNT V0.B8, V0.B8                          // 0058200e
+   VCNT V0.B16, V0.B16                        // 0058204e
    WFE                                        // 5f2003d5
    WFI                                        // 7f2003d5
    YIELD                                      // 3f2003d5
index 4366df4b55ef70ee59e317ed568e6fd5e068d8df..ca18c45d9d965d4d6383af8889a35ef2afd2ccf8 100644 (file)
@@ -990,7 +990,7 @@ produces a file named a.out, even if cmd/link does so by invoking the host
 linker in external linking mode.
 
 By default, cmd/link will decide the linking mode as follows: if the only
-packages using cgo are those on a whitelist of standard library
+packages using cgo are those on a list of known standard library
 packages (net, os/user, runtime/cgo), cmd/link will use internal linking
 mode. Otherwise, there are non-standard cgo packages involved, and cmd/link
 will use external linking mode. The first rule means that a build of
index f1af6473c747cf7b69f8a593456c8d12095fec2b..e372259c788e184cf0d9f6fa5b97c2ee5065f161 100644 (file)
@@ -96,7 +96,7 @@ func TestFormats(t *testing.T) {
                        }
 
                        importPath := filepath.Join("cmd/compile", path)
-                       if blacklistedPackages[filepath.ToSlash(importPath)] {
+                       if ignoredPackages[filepath.ToSlash(importPath)] {
                                return filepath.SkipDir
                        }
 
@@ -344,8 +344,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) {
        for index, file := range files {
                ast.Inspect(file, func(n ast.Node) bool {
                        if call, ok := n.(*ast.CallExpr); ok {
-                               // ignore blacklisted functions
-                               if blacklistedFunctions[nodeString(call.Fun)] {
+                               if ignoredFunctions[nodeString(call.Fun)] {
                                        return true
                                }
                                // look for an arguments that might be a format string
@@ -354,7 +353,7 @@ func collectPkgFormats(t *testing.T, pkg *build.Package) {
                                                // make sure we have enough arguments
                                                n := numFormatArgs(s)
                                                if i+1+n > len(call.Args) {
-                                                       t.Errorf("%s: not enough format args (blacklist %s?)", posString(call), nodeString(call.Fun))
+                                                       t.Errorf("%s: not enough format args (ignore %s?)", posString(call), nodeString(call.Fun))
                                                        break // ignore this call
                                                }
                                                // assume last n arguments are to be formatted;
@@ -549,14 +548,14 @@ func formatReplace(in string, f func(i int, s string) string) string {
        return string(append(buf, in[i0:]...))
 }
 
-// blacklistedPackages is the set of packages which can
+// ignoredPackages is the set of packages which can
 // be ignored.
-var blacklistedPackages = map[string]bool{}
+var ignoredPackages = map[string]bool{}
 
-// blacklistedFunctions is the set of functions which may have
+// ignoredFunctions is the set of functions which may have
 // format-like arguments but which don't do any formatting and
 // thus may be ignored.
-var blacklistedFunctions = map[string]bool{}
+var ignoredFunctions = map[string]bool{}
 
 func init() {
        // verify that knownFormats entries are correctly formatted
index 6f69abf4fb67b5cd1b79645850016f0a5edd2330..cb7a7d9af8f72851d4dc7a4c16c5b7360497e5e2 100644 (file)
@@ -140,6 +140,7 @@ var knownFormats = map[string]string{
        "float64 %.3f":                                    "",
        "float64 %.6g":                                    "",
        "float64 %g":                                      "",
+       "int %#x":                                         "",
        "int %-12d":                                       "",
        "int %-6d":                                        "",
        "int %-8o":                                        "",
@@ -203,6 +204,7 @@ var knownFormats = map[string]string{
        "uint64 %b":            "",
        "uint64 %d":            "",
        "uint64 %x":            "",
+       "uint8 %#x":            "",
        "uint8 %d":             "",
        "uint8 %v":             "",
        "uint8 %x":             "",
index 9935616f413d29278d85df58417db9fca9d6fade..1da72aaf56f9d15abdbe70c0f4d01220d05c1244 100644 (file)
@@ -888,16 +888,30 @@ var condBits = map[ssa.Op]uint8{
 var blockJump = map[ssa.BlockKind]struct {
        asm, invasm obj.As
 }{
-       ssa.BlockARMEQ:  {arm.ABEQ, arm.ABNE},
-       ssa.BlockARMNE:  {arm.ABNE, arm.ABEQ},
-       ssa.BlockARMLT:  {arm.ABLT, arm.ABGE},
-       ssa.BlockARMGE:  {arm.ABGE, arm.ABLT},
-       ssa.BlockARMLE:  {arm.ABLE, arm.ABGT},
-       ssa.BlockARMGT:  {arm.ABGT, arm.ABLE},
-       ssa.BlockARMULT: {arm.ABLO, arm.ABHS},
-       ssa.BlockARMUGE: {arm.ABHS, arm.ABLO},
-       ssa.BlockARMUGT: {arm.ABHI, arm.ABLS},
-       ssa.BlockARMULE: {arm.ABLS, arm.ABHI},
+       ssa.BlockARMEQ:     {arm.ABEQ, arm.ABNE},
+       ssa.BlockARMNE:     {arm.ABNE, arm.ABEQ},
+       ssa.BlockARMLT:     {arm.ABLT, arm.ABGE},
+       ssa.BlockARMGE:     {arm.ABGE, arm.ABLT},
+       ssa.BlockARMLE:     {arm.ABLE, arm.ABGT},
+       ssa.BlockARMGT:     {arm.ABGT, arm.ABLE},
+       ssa.BlockARMULT:    {arm.ABLO, arm.ABHS},
+       ssa.BlockARMUGE:    {arm.ABHS, arm.ABLO},
+       ssa.BlockARMUGT:    {arm.ABHI, arm.ABLS},
+       ssa.BlockARMULE:    {arm.ABLS, arm.ABHI},
+       ssa.BlockARMLTnoov: {arm.ABMI, arm.ABPL},
+       ssa.BlockARMGEnoov: {arm.ABPL, arm.ABMI},
+}
+
+// To model a 'LEnoov' ('<=' without overflow checking) branching
+var leJumps = [2][2]gc.IndexJump{
+       {{Jump: arm.ABEQ, Index: 0}, {Jump: arm.ABPL, Index: 1}}, // next == b.Succs[0]
+       {{Jump: arm.ABMI, Index: 0}, {Jump: arm.ABEQ, Index: 0}}, // next == b.Succs[1]
+}
+
+// To model a 'GTnoov' ('>' without overflow checking) branching
+var gtJumps = [2][2]gc.IndexJump{
+       {{Jump: arm.ABMI, Index: 1}, {Jump: arm.ABEQ, Index: 1}}, // next == b.Succs[0]
+       {{Jump: arm.ABEQ, Index: 1}, {Jump: arm.ABPL, Index: 0}}, // next == b.Succs[1]
 }
 
 func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
@@ -941,7 +955,8 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
                ssa.BlockARMLT, ssa.BlockARMGE,
                ssa.BlockARMLE, ssa.BlockARMGT,
                ssa.BlockARMULT, ssa.BlockARMUGT,
-               ssa.BlockARMULE, ssa.BlockARMUGE:
+               ssa.BlockARMULE, ssa.BlockARMUGE,
+               ssa.BlockARMLTnoov, ssa.BlockARMGEnoov:
                jmp := blockJump[b.Kind]
                switch next {
                case b.Succs[0].Block():
@@ -958,6 +973,12 @@ func ssaGenBlock(s *gc.SSAGenState, b, next *ssa.Block) {
                        }
                }
 
+       case ssa.BlockARMLEnoov:
+               s.CombJump(b, next, &leJumps)
+
+       case ssa.BlockARMGTnoov:
+               s.CombJump(b, next, &gtJumps)
+
        default:
                b.Fatalf("branch not implemented: %s", b.LongString())
        }
index 8e781a7997c82f4958ecc94c6c0dc5e88cff55ff..f3e9ab78ef06814a28e00a6d93ebab7de2413d55 100644 (file)
@@ -141,13 +141,13 @@ func isSelfAssign(dst, src *Node) bool {
        return samesafeexpr(dst.Left, src.Left)
 }
 
-// mayAffectMemory reports whether n evaluation may affect program memory state.
-// If expression can't affect it, then it can be safely ignored by the escape analysis.
+// mayAffectMemory reports whether evaluation of n may affect the program's
+// memory state. If the expression can't affect memory state, then it can be
+// safely ignored by the escape analysis.
 func mayAffectMemory(n *Node) bool {
-       // We may want to use "memory safe" black list instead of general
-       // "side-effect free", which can include all calls and other ops
-       // that can affect allocate or change global state.
-       // It's safer to start from a whitelist for now.
+       // We may want to use a list of "memory safe" ops instead of generally
+       // "side-effect free", which would include all calls and other ops that can
+       // allocate or change global state. For now, it's safer to start with the latter.
        //
        // We're ignoring things like division by zero, index out of range,
        // and nil pointer dereference here.
index 2dbe9cf405242102edfa40bb552f3207e14cbdc3..dbdd027716a12b250d73220ed1a55b549f9e19e3 100644 (file)
@@ -451,6 +451,7 @@ var passes = [...]pass{
        {name: "lowered deadcode for cse", fn: deadcode}, // deadcode immediately before CSE avoids CSE making dead values live again
        {name: "lowered cse", fn: cse},
        {name: "elim unread autos", fn: elimUnreadAutos},
+       {name: "tighten tuple selectors", fn: tightenTupleSelectors, required: true},
        {name: "lowered deadcode", fn: deadcode, required: true},
        {name: "checkLower", fn: checkLower, required: true},
        {name: "late phielim", fn: phielim},
@@ -509,6 +510,8 @@ var passOrder = [...]constraint{
        {"decompose builtin", "late opt"},
        // decompose builtin is the last pass that may introduce new float ops, so run softfloat after it
        {"decompose builtin", "softfloat"},
+       // tuple selectors must be tightened to generators and de-duplicated before scheduling
+       {"tighten tuple selectors", "schedule"},
        // remove critical edges before phi tighten, so that phi args get better placement
        {"critical", "phi tighten"},
        // don't layout blocks until critical edges have been removed
index 6bfd2960c1882b87cca29f5be05589d24be2eaef..3b4f2be37e7beabe44ec6e569be52d4660604056 100644 (file)
@@ -223,60 +223,6 @@ func cse(f *Func) {
                }
        }
 
-       // Fixup tuple selectors.
-       //
-       // If we have rewritten a tuple generator to a new one in a different
-       // block, copy its selectors to the new generator's block, so tuple
-       // generator and selectors stay together.
-       //
-       // Note: that there must be only one selector of each type per tuple
-       // generator. CSE may have left us with more than one so we de-duplicate
-       // them using a map. See issue 16741.
-       selectors := make(map[struct {
-               id ID
-               op Op
-       }]*Value)
-       for _, b := range f.Blocks {
-               for _, selector := range b.Values {
-                       if selector.Op != OpSelect0 && selector.Op != OpSelect1 {
-                               continue
-                       }
-
-                       // Get the tuple generator to use as a key for de-duplication.
-                       tuple := selector.Args[0]
-                       if !tuple.Type.IsTuple() {
-                               f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString())
-                       }
-
-                       // If there is a pre-existing selector in the target block then
-                       // use that. Do this even if the selector is already in the
-                       // target block to avoid duplicate tuple selectors.
-                       key := struct {
-                               id ID
-                               op Op
-                       }{tuple.ID, selector.Op}
-                       if t := selectors[key]; t != nil {
-                               if selector != t {
-                                       selector.copyOf(t)
-                               }
-                               continue
-                       }
-
-                       // If the selector is in the wrong block copy it into the target
-                       // block.
-                       if selector.Block != tuple.Block {
-                               t := selector.copyInto(tuple.Block)
-                               selector.copyOf(t)
-                               selectors[key] = t
-                               continue
-                       }
-
-                       // The selector is in the target block. Add it to the map so it
-                       // cannot be duplicated.
-                       selectors[key] = selector
-               }
-       }
-
        if f.pass.stats > 0 {
                f.LogStat("CSE REWRITES", rewrites)
        }
index a8cea68c5faab15c9b1ff9a75e0f6fcf3adc4110..5b3179acbee291136cdc4ded53a5274c14d3223a 100644 (file)
 (UGE (InvertFlags cmp) yes no) -> (ULE cmp yes no)
 (EQ (InvertFlags cmp) yes no) -> (EQ cmp yes no)
 (NE (InvertFlags cmp) yes no) -> (NE cmp yes no)
+(LTnoov (InvertFlags cmp) yes no) => (GTnoov cmp yes no)
+(GEnoov (InvertFlags cmp) yes no) => (LEnoov cmp yes no)
+(LEnoov (InvertFlags cmp) yes no) => (GEnoov cmp yes no)
+(GTnoov (InvertFlags cmp) yes no) => (LTnoov cmp yes no)
 
 // absorb flag constants into boolean values
 (Equal (FlagEQ)) -> (MOVWconst [1])
 (NE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftLLreg x y z) yes no)
 (NE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRLreg x y z) yes no)
 (NE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (NE (TEQshiftRAreg x y z) yes no)
-(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LT (CMP x y) yes no)
-(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LT (CMP a (MUL <x.Type> x y)) yes no)
-(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LT (CMPconst [c] x) yes no)
-(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftLL x y [c]) yes no)
-(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRL x y [c]) yes no)
-(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMPshiftRA x y [c]) yes no)
-(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftLLreg x y z) yes no)
-(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRLreg x y z) yes no)
-(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMPshiftRAreg x y z) yes no)
-(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LE (CMP x y) yes no)
-(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LE (CMP a (MUL <x.Type> x y)) yes no)
-(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LE (CMPconst [c] x) yes no)
-(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftLL x y [c]) yes no)
-(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRL x y [c]) yes no)
-(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMPshiftRA x y [c]) yes no)
-(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftLLreg x y z) yes no)
-(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRLreg x y z) yes no)
-(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMPshiftRAreg x y z) yes no)
-(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LT (CMN x y) yes no)
-(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LT (CMN a (MUL <x.Type> x y)) yes no)
-(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LT (CMNconst [c] x) yes no)
-(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftLL x y [c]) yes no)
-(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRL x y [c]) yes no)
-(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LT (CMNshiftRA x y [c]) yes no)
-(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftLLreg x y z) yes no)
-(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRLreg x y z) yes no)
-(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LT (CMNshiftRAreg x y z) yes no)
-(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LE (CMN x y) yes no)
-(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LE (CMN a (MUL <x.Type> x y)) yes no)
-(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1  -> (LE (CMNconst [c] x) yes no)
-(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftLL x y [c]) yes no)
-(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRL x y [c]) yes no)
-(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LE (CMNshiftRA x y [c]) yes no)
-(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftLLreg x y z) yes no)
-(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRLreg x y z) yes no)
-(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (CMNshiftRAreg x y z) yes no)
+(LT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LTnoov (CMP x y) yes no)
+(LT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LTnoov (CMP a (MUL <x.Type> x y)) yes no)
+(LT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (CMPconst [c] x) yes no)
+(LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftLL x y [c]) yes no)
+(LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRL x y [c]) yes no)
+(LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRA x y [c]) yes no)
+(LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftLLreg x y z) yes no)
+(LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRLreg x y z) yes no)
+(LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMPshiftRAreg x y z) yes no)
+(LE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (LEnoov (CMP x y) yes no)
+(LE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (LEnoov (CMP a (MUL <x.Type> x y)) yes no)
+(LE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (LEnoov (CMPconst [c] x) yes no)
+(LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftLL x y [c]) yes no)
+(LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRL x y [c]) yes no)
+(LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRA x y [c]) yes no)
+(LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftLLreg x y z) yes no)
+(LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRLreg x y z) yes no)
+(LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMPshiftRAreg x y z) yes no)
+(LT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LTnoov (CMN x y) yes no)
+(LT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
+(LT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (LTnoov (CMNconst [c] x) yes no)
+(LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftLL x y [c]) yes no)
+(LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRL x y [c]) yes no)
+(LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRA x y [c]) yes no)
+(LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftLLreg x y z) yes no)
+(LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRLreg x y z) yes no)
+(LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LTnoov (CMNshiftRAreg x y z) yes no)
+(LE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (LEnoov (CMN x y) yes no)
+(LE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
+(LE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1  -> (LEnoov (CMNconst [c] x) yes no)
+(LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLL x y [c]) yes no)
+(LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRL x y [c]) yes no)
+(LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRA x y [c]) yes no)
+(LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftLLreg x y z) yes no)
+(LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRLreg x y z) yes no)
+(LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (LEnoov (CMNshiftRAreg x y z) yes no)
 (LT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (LT (TST x y) yes no)
 (LT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (LT (TSTconst [c] x) yes no)
 (LT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (LT (TSTshiftLL x y [c]) yes no)
 (LE (CMPconst [0] l:(XORshiftLLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftLLreg x y z) yes no)
 (LE (CMPconst [0] l:(XORshiftRLreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRLreg x y z) yes no)
 (LE (CMPconst [0] l:(XORshiftRAreg x y z)) yes no) && l.Uses==1 -> (LE (TEQshiftRAreg x y z) yes no)
-(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GT (CMP x y) yes no)
-(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GT (CMP a (MUL <x.Type> x y)) yes no)
-(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GT (CMPconst [c] x) yes no)
-(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftLL x y [c]) yes no)
-(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRL x y [c]) yes no)
-(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMPshiftRA x y [c]) yes no)
-(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftLLreg x y z) yes no)
-(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRLreg x y z) yes no)
-(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMPshiftRAreg x y z) yes no)
-(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GE (CMP x y) yes no)
-(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GE (CMP a (MUL <x.Type> x y)) yes no)
-(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GE (CMPconst [c] x) yes no)
-(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftLL x y [c]) yes no)
-(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRL x y [c]) yes no)
-(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMPshiftRA x y [c]) yes no)
-(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftLLreg x y z) yes no)
-(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRLreg x y z) yes no)
-(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMPshiftRAreg x y z) yes no)
-(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GT (CMN x y) yes no)
-(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GT (CMNconst [c] x) yes no)
-(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftLL x y [c]) yes no)
-(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRL x y [c]) yes no)
-(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GT (CMNshiftRA x y [c]) yes no)
-(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftLLreg x y z) yes no)
-(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRLreg x y z) yes no)
-(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GT (CMNshiftRAreg x y z) yes no)
-(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GE (CMN x y) yes no)
-(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GE (CMN a (MUL <x.Type> x y)) yes no)
-(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GE (CMNconst [c] x) yes no)
-(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftLL x y [c]) yes no)
-(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRL x y [c]) yes no)
-(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GE (CMNshiftRA x y [c]) yes no)
-(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftLLreg x y z) yes no)
-(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRLreg x y z) yes no)
-(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GE (CMNshiftRAreg x y z) yes no)
+(GT (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GTnoov (CMP x y) yes no)
+(GT (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GTnoov (CMP a (MUL <x.Type> x y)) yes no)
+(GT (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMPconst [c] x) yes no)
+(GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftLL x y [c]) yes no)
+(GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRL x y [c]) yes no)
+(GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRA x y [c]) yes no)
+(GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftLLreg x y z) yes no)
+(GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRLreg x y z) yes no)
+(GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMPshiftRAreg x y z) yes no)
+(GE (CMPconst [0] l:(SUB x y)) yes no) && l.Uses==1 -> (GEnoov (CMP x y) yes no)
+(GE (CMPconst [0] l:(MULS x y a)) yes no) && l.Uses==1 -> (GEnoov (CMP a (MUL <x.Type> x y)) yes no)
+(GE (CMPconst [0] l:(SUBconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (CMPconst [c] x) yes no)
+(GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftLL x y [c]) yes no)
+(GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRL x y [c]) yes no)
+(GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRA x y [c]) yes no)
+(GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftLLreg x y z) yes no)
+(GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRLreg x y z) yes no)
+(GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMPshiftRAreg x y z) yes no)
+(GT (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GTnoov (CMN x y) yes no)
+(GT (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GTnoov (CMNconst [c] x) yes no)
+(GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftLL x y [c]) yes no)
+(GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRL x y [c]) yes no)
+(GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRA x y [c]) yes no)
+(GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftLLreg x y z) yes no)
+(GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRLreg x y z) yes no)
+(GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GTnoov (CMNshiftRAreg x y z) yes no)
+(GE (CMPconst [0] l:(ADD x y)) yes no) && l.Uses==1 -> (GEnoov (CMN x y) yes no)
+(GE (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
+(GE (CMPconst [0] l:(ADDconst [c] x)) yes no) && l.Uses==1 -> (GEnoov (CMNconst [c] x) yes no)
+(GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLL x y [c]) yes no)
+(GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRL x y [c]) yes no)
+(GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRA x y [c]) yes no)
+(GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftLLreg x y z) yes no)
+(GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRLreg x y z) yes no)
+(GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no) && l.Uses==1 -> (GEnoov (CMNshiftRAreg x y z) yes no)
 (GT (CMPconst [0] l:(AND x y)) yes no) && l.Uses==1 -> (GT (TST x y) yes no)
-(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GT (CMN a (MUL <x.Type> x y)) yes no)
+(GT (CMPconst [0] l:(MULA x y a)) yes no) && l.Uses==1 -> (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
 (GT (CMPconst [0] l:(ANDconst [c] x)) yes no) && l.Uses==1 -> (GT (TSTconst [c] x) yes no)
 (GT (CMPconst [0] l:(ANDshiftLL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftLL x y [c]) yes no)
 (GT (CMPconst [0] l:(ANDshiftRL x y [c])) yes no) && l.Uses==1 -> (GT (TSTshiftRL x y [c]) yes no)
index 4abe5c9a8b69f740d4d7a1356ce50843626c8dfc..14407feaa28d73385df65c7efe8b305d52a276a0 100644 (file)
@@ -584,6 +584,10 @@ func init() {
                {name: "ULE", controls: 1},
                {name: "UGT", controls: 1},
                {name: "UGE", controls: 1},
+               {name: "LTnoov", controls: 1}, // 'LT' but without honoring overflow
+               {name: "LEnoov", controls: 1}, // 'LE' but without honoring overflow
+               {name: "GTnoov", controls: 1}, // 'GT' but without honoring overflow
+               {name: "GEnoov", controls: 1}, // 'GE' but without honoring overflow
        }
 
        archs = append(archs, arch{
index 4a83a46be2c84d61afa6886b1466558efcd6c43a..7f6bf3e15bed0d0d34786ce4ac731317af8f46e9 100644 (file)
@@ -61,6 +61,10 @@ const (
        BlockARMULE
        BlockARMUGT
        BlockARMUGE
+       BlockARMLTnoov
+       BlockARMLEnoov
+       BlockARMGTnoov
+       BlockARMGEnoov
 
        BlockARM64EQ
        BlockARM64NE
@@ -185,16 +189,20 @@ var blockString = [...]string{
        BlockAMD64ORD: "ORD",
        BlockAMD64NAN: "NAN",
 
-       BlockARMEQ:  "EQ",
-       BlockARMNE:  "NE",
-       BlockARMLT:  "LT",
-       BlockARMLE:  "LE",
-       BlockARMGT:  "GT",
-       BlockARMGE:  "GE",
-       BlockARMULT: "ULT",
-       BlockARMULE: "ULE",
-       BlockARMUGT: "UGT",
-       BlockARMUGE: "UGE",
+       BlockARMEQ:     "EQ",
+       BlockARMNE:     "NE",
+       BlockARMLT:     "LT",
+       BlockARMLE:     "LE",
+       BlockARMGT:     "GT",
+       BlockARMGE:     "GE",
+       BlockARMULT:    "ULT",
+       BlockARMULE:    "ULE",
+       BlockARMUGT:    "UGT",
+       BlockARMUGE:    "UGE",
+       BlockARMLTnoov: "LTnoov",
+       BlockARMLEnoov: "LEnoov",
+       BlockARMGTnoov: "GTnoov",
+       BlockARMGEnoov: "GEnoov",
 
        BlockARM64EQ:     "EQ",
        BlockARM64NE:     "NE",
index 5c8dd0f2edd5f5383cffe162e66e136994acfbed..be5f56a1f7a27fc5ae8903eb2726d6bd0f357943 100644 (file)
@@ -17514,7 +17514,7 @@ func rewriteBlockARM(b *Block) bool {
                }
                // match: (GE (CMPconst [0] l:(SUB x y)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMP x y) yes no)
+               // result: (GEnoov (CMP x y) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17531,12 +17531,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(MULS x y a)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMP a (MUL <x.Type> x y)) yes no)
+               // result: (GEnoov (CMP a (MUL <x.Type> x y)) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17556,12 +17556,12 @@ func rewriteBlockARM(b *Block) bool {
                        v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
                        v1.AddArg2(x, y)
                        v0.AddArg2(a, v1)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(SUBconst [c] x)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMPconst [c] x) yes no)
+               // result: (GEnoov (CMPconst [c] x) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17579,12 +17579,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg(x)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMPshiftLL x y [c]) yes no)
+               // result: (GEnoov (CMPshiftLL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17603,12 +17603,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMPshiftRL x y [c]) yes no)
+               // result: (GEnoov (CMPshiftRL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17627,12 +17627,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMPshiftRA x y [c]) yes no)
+               // result: (GEnoov (CMPshiftRA x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17651,12 +17651,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMPshiftLLreg x y z) yes no)
+               // result: (GEnoov (CMPshiftLLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17674,12 +17674,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMPshiftRLreg x y z) yes no)
+               // result: (GEnoov (CMPshiftRLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17697,12 +17697,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMPshiftRAreg x y z) yes no)
+               // result: (GEnoov (CMPshiftRAreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17720,12 +17720,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(ADD x y)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMN x y) yes no)
+               // result: (GEnoov (CMN x y) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17746,14 +17746,14 @@ func rewriteBlockARM(b *Block) bool {
                                }
                                v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
                                v0.AddArg2(x, y)
-                               b.resetWithControl(BlockARMGE, v0)
+                               b.resetWithControl(BlockARMGEnoov, v0)
                                return true
                        }
                        break
                }
                // match: (GE (CMPconst [0] l:(MULA x y a)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMN a (MUL <x.Type> x y)) yes no)
+               // result: (GEnoov (CMN a (MUL <x.Type> x y)) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17773,12 +17773,12 @@ func rewriteBlockARM(b *Block) bool {
                        v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
                        v1.AddArg2(x, y)
                        v0.AddArg2(a, v1)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(ADDconst [c] x)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMNconst [c] x) yes no)
+               // result: (GEnoov (CMNconst [c] x) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17796,12 +17796,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg(x)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMNshiftLL x y [c]) yes no)
+               // result: (GEnoov (CMNshiftLL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17820,12 +17820,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMNshiftRL x y [c]) yes no)
+               // result: (GEnoov (CMNshiftRL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17844,12 +17844,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMNshiftRA x y [c]) yes no)
+               // result: (GEnoov (CMNshiftRA x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17868,12 +17868,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMNshiftLLreg x y z) yes no)
+               // result: (GEnoov (CMNshiftLLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17891,12 +17891,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMNshiftRLreg x y z) yes no)
+               // result: (GEnoov (CMNshiftRLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17914,12 +17914,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GE (CMNshiftRAreg x y z) yes no)
+               // result: (GEnoov (CMNshiftRAreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -17937,7 +17937,7 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGE, v0)
+                       b.resetWithControl(BlockARMGEnoov, v0)
                        return true
                }
                // match: (GE (CMPconst [0] l:(AND x y)) yes no)
@@ -18324,6 +18324,15 @@ func rewriteBlockARM(b *Block) bool {
                        b.resetWithControl(BlockARMGE, v0)
                        return true
                }
+       case BlockARMGEnoov:
+               // match: (GEnoov (InvertFlags cmp) yes no)
+               // result: (LEnoov cmp yes no)
+               for b.Controls[0].Op == OpARMInvertFlags {
+                       v_0 := b.Controls[0]
+                       cmp := v_0.Args[0]
+                       b.resetWithControl(BlockARMLEnoov, cmp)
+                       return true
+               }
        case BlockARMGT:
                // match: (GT (FlagEQ) yes no)
                // result: (First no yes)
@@ -18368,7 +18377,7 @@ func rewriteBlockARM(b *Block) bool {
                }
                // match: (GT (CMPconst [0] l:(SUB x y)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMP x y) yes no)
+               // result: (GTnoov (CMP x y) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18385,12 +18394,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(MULS x y a)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMP a (MUL <x.Type> x y)) yes no)
+               // result: (GTnoov (CMP a (MUL <x.Type> x y)) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18410,12 +18419,12 @@ func rewriteBlockARM(b *Block) bool {
                        v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
                        v1.AddArg2(x, y)
                        v0.AddArg2(a, v1)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(SUBconst [c] x)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMPconst [c] x) yes no)
+               // result: (GTnoov (CMPconst [c] x) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18433,12 +18442,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg(x)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMPshiftLL x y [c]) yes no)
+               // result: (GTnoov (CMPshiftLL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18457,12 +18466,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMPshiftRL x y [c]) yes no)
+               // result: (GTnoov (CMPshiftRL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18481,12 +18490,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMPshiftRA x y [c]) yes no)
+               // result: (GTnoov (CMPshiftRA x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18505,12 +18514,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMPshiftLLreg x y z) yes no)
+               // result: (GTnoov (CMPshiftLLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18528,12 +18537,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMPshiftRLreg x y z) yes no)
+               // result: (GTnoov (CMPshiftRLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18551,12 +18560,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMPshiftRAreg x y z) yes no)
+               // result: (GTnoov (CMPshiftRAreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18574,12 +18583,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(ADD x y)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMN x y) yes no)
+               // result: (GTnoov (CMN x y) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18600,14 +18609,14 @@ func rewriteBlockARM(b *Block) bool {
                                }
                                v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
                                v0.AddArg2(x, y)
-                               b.resetWithControl(BlockARMGT, v0)
+                               b.resetWithControl(BlockARMGTnoov, v0)
                                return true
                        }
                        break
                }
                // match: (GT (CMPconst [0] l:(ADDconst [c] x)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMNconst [c] x) yes no)
+               // result: (GTnoov (CMNconst [c] x) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18625,12 +18634,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg(x)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMNshiftLL x y [c]) yes no)
+               // result: (GTnoov (CMNshiftLL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18649,12 +18658,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMNshiftRL x y [c]) yes no)
+               // result: (GTnoov (CMNshiftRL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18673,12 +18682,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMNshiftRA x y [c]) yes no)
+               // result: (GTnoov (CMNshiftRA x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18697,12 +18706,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMNshiftLLreg x y z) yes no)
+               // result: (GTnoov (CMNshiftLLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18720,12 +18729,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMNshiftRLreg x y z) yes no)
+               // result: (GTnoov (CMNshiftRLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18743,12 +18752,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMNshiftRAreg x y z) yes no)
+               // result: (GTnoov (CMNshiftRAreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18766,7 +18775,7 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(AND x y)) yes no)
@@ -18799,7 +18808,7 @@ func rewriteBlockARM(b *Block) bool {
                }
                // match: (GT (CMPconst [0] l:(MULA x y a)) yes no)
                // cond: l.Uses==1
-               // result: (GT (CMN a (MUL <x.Type> x y)) yes no)
+               // result: (GTnoov (CMN a (MUL <x.Type> x y)) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -18819,7 +18828,7 @@ func rewriteBlockARM(b *Block) bool {
                        v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
                        v1.AddArg2(x, y)
                        v0.AddArg2(a, v1)
-                       b.resetWithControl(BlockARMGT, v0)
+                       b.resetWithControl(BlockARMGTnoov, v0)
                        return true
                }
                // match: (GT (CMPconst [0] l:(ANDconst [c] x)) yes no)
@@ -19178,6 +19187,15 @@ func rewriteBlockARM(b *Block) bool {
                        b.resetWithControl(BlockARMGT, v0)
                        return true
                }
+       case BlockARMGTnoov:
+               // match: (GTnoov (InvertFlags cmp) yes no)
+               // result: (LTnoov cmp yes no)
+               for b.Controls[0].Op == OpARMInvertFlags {
+                       v_0 := b.Controls[0]
+                       cmp := v_0.Args[0]
+                       b.resetWithControl(BlockARMLTnoov, cmp)
+                       return true
+               }
        case BlockIf:
                // match: (If (Equal cc) yes no)
                // result: (EQ cc yes no)
@@ -19312,7 +19330,7 @@ func rewriteBlockARM(b *Block) bool {
                }
                // match: (LE (CMPconst [0] l:(SUB x y)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMP x y) yes no)
+               // result: (LEnoov (CMP x y) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19329,12 +19347,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(MULS x y a)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMP a (MUL <x.Type> x y)) yes no)
+               // result: (LEnoov (CMP a (MUL <x.Type> x y)) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19354,12 +19372,12 @@ func rewriteBlockARM(b *Block) bool {
                        v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
                        v1.AddArg2(x, y)
                        v0.AddArg2(a, v1)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(SUBconst [c] x)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMPconst [c] x) yes no)
+               // result: (LEnoov (CMPconst [c] x) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19377,12 +19395,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg(x)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMPshiftLL x y [c]) yes no)
+               // result: (LEnoov (CMPshiftLL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19401,12 +19419,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMPshiftRL x y [c]) yes no)
+               // result: (LEnoov (CMPshiftRL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19425,12 +19443,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMPshiftRA x y [c]) yes no)
+               // result: (LEnoov (CMPshiftRA x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19449,12 +19467,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMPshiftLLreg x y z) yes no)
+               // result: (LEnoov (CMPshiftLLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19472,12 +19490,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMPshiftRLreg x y z) yes no)
+               // result: (LEnoov (CMPshiftRLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19495,12 +19513,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMPshiftRAreg x y z) yes no)
+               // result: (LEnoov (CMPshiftRAreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19518,12 +19536,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(ADD x y)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMN x y) yes no)
+               // result: (LEnoov (CMN x y) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19544,14 +19562,14 @@ func rewriteBlockARM(b *Block) bool {
                                }
                                v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
                                v0.AddArg2(x, y)
-                               b.resetWithControl(BlockARMLE, v0)
+                               b.resetWithControl(BlockARMLEnoov, v0)
                                return true
                        }
                        break
                }
                // match: (LE (CMPconst [0] l:(MULA x y a)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMN a (MUL <x.Type> x y)) yes no)
+               // result: (LEnoov (CMN a (MUL <x.Type> x y)) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19571,12 +19589,12 @@ func rewriteBlockARM(b *Block) bool {
                        v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
                        v1.AddArg2(x, y)
                        v0.AddArg2(a, v1)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(ADDconst [c] x)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMNconst [c] x) yes no)
+               // result: (LEnoov (CMNconst [c] x) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19594,12 +19612,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg(x)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMNshiftLL x y [c]) yes no)
+               // result: (LEnoov (CMNshiftLL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19618,12 +19636,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMNshiftRL x y [c]) yes no)
+               // result: (LEnoov (CMNshiftRL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19642,12 +19660,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMNshiftRA x y [c]) yes no)
+               // result: (LEnoov (CMNshiftRA x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19666,12 +19684,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMNshiftLLreg x y z) yes no)
+               // result: (LEnoov (CMNshiftLLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19689,12 +19707,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMNshiftRLreg x y z) yes no)
+               // result: (LEnoov (CMNshiftRLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19712,12 +19730,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LE (CMNshiftRAreg x y z) yes no)
+               // result: (LEnoov (CMNshiftRAreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -19735,7 +19753,7 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLE, v0)
+                       b.resetWithControl(BlockARMLEnoov, v0)
                        return true
                }
                // match: (LE (CMPconst [0] l:(AND x y)) yes no)
@@ -20122,6 +20140,15 @@ func rewriteBlockARM(b *Block) bool {
                        b.resetWithControl(BlockARMLE, v0)
                        return true
                }
+       case BlockARMLEnoov:
+               // match: (LEnoov (InvertFlags cmp) yes no)
+               // result: (GEnoov cmp yes no)
+               for b.Controls[0].Op == OpARMInvertFlags {
+                       v_0 := b.Controls[0]
+                       cmp := v_0.Args[0]
+                       b.resetWithControl(BlockARMGEnoov, cmp)
+                       return true
+               }
        case BlockARMLT:
                // match: (LT (FlagEQ) yes no)
                // result: (First no yes)
@@ -20166,7 +20193,7 @@ func rewriteBlockARM(b *Block) bool {
                }
                // match: (LT (CMPconst [0] l:(SUB x y)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMP x y) yes no)
+               // result: (LTnoov (CMP x y) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20183,12 +20210,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMP, types.TypeFlags)
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(MULS x y a)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMP a (MUL <x.Type> x y)) yes no)
+               // result: (LTnoov (CMP a (MUL <x.Type> x y)) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20208,12 +20235,12 @@ func rewriteBlockARM(b *Block) bool {
                        v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
                        v1.AddArg2(x, y)
                        v0.AddArg2(a, v1)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(SUBconst [c] x)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMPconst [c] x) yes no)
+               // result: (LTnoov (CMPconst [c] x) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20231,12 +20258,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPconst, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg(x)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(SUBshiftLL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMPshiftLL x y [c]) yes no)
+               // result: (LTnoov (CMPshiftLL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20255,12 +20282,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(SUBshiftRL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMPshiftRL x y [c]) yes no)
+               // result: (LTnoov (CMPshiftRL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20279,12 +20306,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(SUBshiftRA x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMPshiftRA x y [c]) yes no)
+               // result: (LTnoov (CMPshiftRA x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20303,12 +20330,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRA, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(SUBshiftLLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMPshiftLLreg x y z) yes no)
+               // result: (LTnoov (CMPshiftLLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20326,12 +20353,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftLLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(SUBshiftRLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMPshiftRLreg x y z) yes no)
+               // result: (LTnoov (CMPshiftRLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20349,12 +20376,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(SUBshiftRAreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMPshiftRAreg x y z) yes no)
+               // result: (LTnoov (CMPshiftRAreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20372,12 +20399,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMPshiftRAreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(ADD x y)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMN x y) yes no)
+               // result: (LTnoov (CMN x y) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20398,14 +20425,14 @@ func rewriteBlockARM(b *Block) bool {
                                }
                                v0 := b.NewValue0(v_0.Pos, OpARMCMN, types.TypeFlags)
                                v0.AddArg2(x, y)
-                               b.resetWithControl(BlockARMLT, v0)
+                               b.resetWithControl(BlockARMLTnoov, v0)
                                return true
                        }
                        break
                }
                // match: (LT (CMPconst [0] l:(MULA x y a)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMN a (MUL <x.Type> x y)) yes no)
+               // result: (LTnoov (CMN a (MUL <x.Type> x y)) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20425,12 +20452,12 @@ func rewriteBlockARM(b *Block) bool {
                        v1 := b.NewValue0(v_0.Pos, OpARMMUL, x.Type)
                        v1.AddArg2(x, y)
                        v0.AddArg2(a, v1)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(ADDconst [c] x)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMNconst [c] x) yes no)
+               // result: (LTnoov (CMNconst [c] x) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20448,12 +20475,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNconst, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg(x)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(ADDshiftLL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMNshiftLL x y [c]) yes no)
+               // result: (LTnoov (CMNshiftLL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20472,12 +20499,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(ADDshiftRL x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMNshiftRL x y [c]) yes no)
+               // result: (LTnoov (CMNshiftRL x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20496,12 +20523,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRL, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(ADDshiftRA x y [c])) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMNshiftRA x y [c]) yes no)
+               // result: (LTnoov (CMNshiftRA x y [c]) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20520,12 +20547,12 @@ func rewriteBlockARM(b *Block) bool {
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRA, types.TypeFlags)
                        v0.AuxInt = c
                        v0.AddArg2(x, y)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(ADDshiftLLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMNshiftLLreg x y z) yes no)
+               // result: (LTnoov (CMNshiftLLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20543,12 +20570,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftLLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(ADDshiftRLreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMNshiftRLreg x y z) yes no)
+               // result: (LTnoov (CMNshiftRLreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20566,12 +20593,12 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRLreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(ADDshiftRAreg x y z)) yes no)
                // cond: l.Uses==1
-               // result: (LT (CMNshiftRAreg x y z) yes no)
+               // result: (LTnoov (CMNshiftRAreg x y z) yes no)
                for b.Controls[0].Op == OpARMCMPconst {
                        v_0 := b.Controls[0]
                        if v_0.AuxInt != 0 {
@@ -20589,7 +20616,7 @@ func rewriteBlockARM(b *Block) bool {
                        }
                        v0 := b.NewValue0(v_0.Pos, OpARMCMNshiftRAreg, types.TypeFlags)
                        v0.AddArg3(x, y, z)
-                       b.resetWithControl(BlockARMLT, v0)
+                       b.resetWithControl(BlockARMLTnoov, v0)
                        return true
                }
                // match: (LT (CMPconst [0] l:(AND x y)) yes no)
@@ -20976,6 +21003,15 @@ func rewriteBlockARM(b *Block) bool {
                        b.resetWithControl(BlockARMLT, v0)
                        return true
                }
+       case BlockARMLTnoov:
+               // match: (LTnoov (InvertFlags cmp) yes no)
+               // result: (GTnoov cmp yes no)
+               for b.Controls[0].Op == OpARMInvertFlags {
+                       v_0 := b.Controls[0]
+                       cmp := v_0.Args[0]
+                       b.resetWithControl(BlockARMGTnoov, cmp)
+                       return true
+               }
        case BlockARMNE:
                // match: (NE (CMPconst [0] (Equal cc)) yes no)
                // result: (EQ cc yes no)
index 6536d3a7d78ba5001a257c7fe09a5cc548ea6c92..2c26fdf1427e20d0ea9d94e15f73d4690abffd22 100644 (file)
@@ -7,24 +7,26 @@ package ssa
 import (
        "math"
        "math/rand"
-       "runtime"
        "testing"
 )
 
 var (
-       x64   int64 = math.MaxInt64 - 2
-       x64b  int64 = math.MaxInt64 - 2
-       x64c  int64 = math.MaxInt64 - 2
-       y64   int64 = math.MinInt64 + 1
-       x32   int32 = math.MaxInt32 - 2
-       x32b  int32 = math.MaxInt32 - 2
-       y32   int32 = math.MinInt32 + 1
-       one64 int64 = 1
-       one32 int32 = 1
-       v64   int64 = 11 // ensure it's not 2**n +/- 1
-       v64_n int64 = -11
-       v32   int32 = 11
-       v32_n int32 = -11
+       x64   int64  = math.MaxInt64 - 2
+       x64b  int64  = math.MaxInt64 - 2
+       x64c  int64  = math.MaxInt64 - 2
+       y64   int64  = math.MinInt64 + 1
+       x32   int32  = math.MaxInt32 - 2
+       x32b  int32  = math.MaxInt32 - 2
+       x32c  int32  = math.MaxInt32 - 2
+       y32   int32  = math.MinInt32 + 1
+       one64 int64  = 1
+       one32 int32  = 1
+       v64   int64  = 11 // ensure it's not 2**n +/- 1
+       v64_n int64  = -11
+       v32   int32  = 11
+       v32_n int32  = -11
+       uv32  uint32 = 19
+       uz    uint8  = 1 // for lowering to SLL/SRL/SRA
 )
 
 var crTests = []struct {
@@ -39,6 +41,8 @@ var crTests = []struct {
        {"MAddVar32", testMAddVar32},
        {"MSubVar64", testMSubVar64},
        {"MSubVar32", testMSubVar32},
+       {"AddShift32", testAddShift32},
+       {"SubShift32", testSubShift32},
 }
 
 var crBenches = []struct {
@@ -58,9 +62,6 @@ var crBenches = []struct {
 // and machine code sequences are covered.
 // It's for arm64 initially, please see https://github.com/golang/go/issues/38740
 func TestCondRewrite(t *testing.T) {
-       if runtime.GOARCH == "arm" {
-               t.Skip("fix on arm expected!")
-       }
        for _, test := range crTests {
                t.Run(test.name, test.tf)
        }
@@ -408,6 +409,66 @@ func testMSubVar32(t *testing.T) {
        }
 }
 
+// 32-bit ADDshift, pick up 1~2 scenarios randomly for each condition
+func testAddShift32(t *testing.T) {
+       if x32+v32<<1 < 0 {
+       } else {
+               t.Errorf("'%#x + %#x<<%#x < 0' failed", x32, v32, 1)
+       }
+
+       if x32+v32>>1 <= 0 {
+       } else {
+               t.Errorf("'%#x + %#x>>%#x <= 0' failed", x32, v32, 1)
+       }
+
+       if x32+int32(uv32>>1) > 0 {
+               t.Errorf("'%#x + int32(%#x>>%#x) > 0' failed", x32, uv32, 1)
+       }
+
+       if x32+v32<<uz >= 0 {
+               t.Errorf("'%#x + %#x<<%#x >= 0' failed", x32, v32, uz)
+       }
+
+       if x32+v32>>uz > 0 {
+               t.Errorf("'%#x + %#x>>%#x > 0' failed", x32, v32, uz)
+       }
+
+       if x32+int32(uv32>>uz) < 0 {
+       } else {
+               t.Errorf("'%#x + int32(%#x>>%#x) < 0' failed", x32, uv32, uz)
+       }
+}
+
+// 32-bit SUBshift, pick up 1~2 scenarios randomly for each condition
+func testSubShift32(t *testing.T) {
+       if y32-v32<<1 > 0 {
+       } else {
+               t.Errorf("'%#x - %#x<<%#x > 0' failed", y32, v32, 1)
+       }
+
+       if y32-v32>>1 < 0 {
+               t.Errorf("'%#x - %#x>>%#x < 0' failed", y32, v32, 1)
+       }
+
+       if y32-int32(uv32>>1) >= 0 {
+       } else {
+               t.Errorf("'%#x - int32(%#x>>%#x) >= 0' failed", y32, uv32, 1)
+       }
+
+       if y32-v32<<uz < 0 {
+               t.Errorf("'%#x - %#x<<%#x < 0' failed", y32, v32, uz)
+       }
+
+       if y32-v32>>uz >= 0 {
+       } else {
+               t.Errorf("'%#x - %#x>>%#x >= 0' failed", y32, v32, uz)
+       }
+
+       if y32-int32(uv32>>uz) <= 0 {
+               t.Errorf("'%#x - int32(%#x>>%#x) <= 0' failed", y32, uv32, uz)
+       }
+}
+
 var rnd = rand.New(rand.NewSource(0))
 var sink int64
 
diff --git a/src/cmd/compile/internal/ssa/tuple.go b/src/cmd/compile/internal/ssa/tuple.go
new file mode 100644 (file)
index 0000000..38deabf
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ssa
+
+// tightenTupleSelectors ensures that tuple selectors (Select0 and
+// Select1 ops) are in the same block as their tuple generator. The
+// function also ensures that there are no duplicate tuple selectors.
+// These properties are expected by the scheduler but may not have
+// been maintained by the optimization pipeline up to this point.
+//
+// See issues 16741 and 39472.
+func tightenTupleSelectors(f *Func) {
+       selectors := make(map[struct {
+               id ID
+               op Op
+       }]*Value)
+       for _, b := range f.Blocks {
+               for _, selector := range b.Values {
+                       if selector.Op != OpSelect0 && selector.Op != OpSelect1 {
+                               continue
+                       }
+
+                       // Get the tuple generator to use as a key for de-duplication.
+                       tuple := selector.Args[0]
+                       if !tuple.Type.IsTuple() {
+                               f.Fatalf("arg of tuple selector %s is not a tuple: %s", selector.String(), tuple.LongString())
+                       }
+
+                       // If there is a pre-existing selector in the target block then
+                       // use that. Do this even if the selector is already in the
+                       // target block to avoid duplicate tuple selectors.
+                       key := struct {
+                               id ID
+                               op Op
+                       }{tuple.ID, selector.Op}
+                       if t := selectors[key]; t != nil {
+                               if selector != t {
+                                       selector.copyOf(t)
+                               }
+                               continue
+                       }
+
+                       // If the selector is in the wrong block copy it into the target
+                       // block.
+                       if selector.Block != tuple.Block {
+                               t := selector.copyInto(tuple.Block)
+                               selector.copyOf(t)
+                               selectors[key] = t
+                               continue
+                       }
+
+                       // The selector is in the target block. Add it to the map so it
+                       // cannot be duplicated.
+                       selectors[key] = selector
+               }
+       }
+}
index 08ef056164aeea0fee16383b234cb6aa75b4939a..e1cd4965c343071365711f4c327f9bd166f11da4 100644 (file)
@@ -178,15 +178,6 @@ func (t *tester) run() {
                return
        }
 
-       // We must unset GOROOT_FINAL before tests, because runtime/debug requires
-       // correct access to source code, so if we have GOROOT_FINAL in effect,
-       // at least runtime/debug test will fail.
-       // If GOROOT_FINAL was set before, then now all the commands will appear stale.
-       // Nothing we can do about that other than not checking them below.
-       // (We call checkNotStale but only with "std" not "cmd".)
-       os.Setenv("GOROOT_FINAL_OLD", os.Getenv("GOROOT_FINAL")) // for cmd/link test
-       os.Unsetenv("GOROOT_FINAL")
-
        for _, name := range t.runNames {
                if !t.isRegisteredTestName(name) {
                        fatalf("unknown test %q", name)
index 4c30de478142415db5903b7efbaef85b7748231e..021930a8a8170106002e7d6cde64b749c43d49be 100644 (file)
@@ -124,7 +124,6 @@ func TestMain(m *testing.M) {
                fmt.Printf("SKIP\n")
                return
        }
-       os.Unsetenv("GOROOT_FINAL")
 
        flag.Parse()
 
@@ -180,6 +179,11 @@ func TestMain(m *testing.M) {
                }
                testGOROOT = goEnv("GOROOT")
                os.Setenv("TESTGO_GOROOT", testGOROOT)
+               // Ensure that GOROOT is set explicitly.
+               // Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
+               // yet been moved to its final location, programs that invoke runtime.GOROOT
+               // may accidentally use the wrong path.
+               os.Setenv("GOROOT", testGOROOT)
 
                // The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
                // toolchain (installed in GOROOT/pkg/tool/GOHOSTOS_GOHOSTARCH).
@@ -216,8 +220,10 @@ func TestMain(m *testing.M) {
                }
                testCC = strings.TrimSpace(string(out))
 
-               if out, err := exec.Command(testGo, "env", "CGO_ENABLED").Output(); err != nil {
-                       fmt.Fprintf(os.Stderr, "running testgo failed: %v\n", err)
+               cmd := exec.Command(testGo, "env", "CGO_ENABLED")
+               cmd.Stderr = new(strings.Builder)
+               if out, err := cmd.Output(); err != nil {
+                       fmt.Fprintf(os.Stderr, "running testgo failed: %v\n%s", err, cmd.Stderr)
                        canRun = false
                } else {
                        canCgo, err = strconv.ParseBool(strings.TrimSpace(string(out)))
index beb80c505dc749cd851ee07496d3445817636598..e0509808d67a2a8422bc5e2ec865256961113da3 100644 (file)
@@ -13,6 +13,7 @@ package web
 
 import (
        "crypto/tls"
+       "errors"
        "fmt"
        "mime"
        "net/http"
@@ -47,6 +48,13 @@ var securityPreservingHTTPClient = &http.Client{
                        lastHop := via[len(via)-1].URL
                        return fmt.Errorf("redirected from secure URL %s to insecure URL %s", lastHop, req.URL)
                }
+
+               // Go's http.DefaultClient allows 10 redirects before returning an error.
+               // The securityPreservingHTTPClient also uses this default policy to avoid
+               // Go command hangs.
+               if len(via) >= 10 {
+                       return errors.New("stopped after 10 redirects")
+               }
                return nil
        },
 }
index 318d688d2e502f2fa49e2ed8d0e48a77a8d1a07a..f1d08e02686c7ed08b9d40999a4e95f908620bba 100644 (file)
@@ -168,7 +168,7 @@ func gcBackendConcurrency(gcflags []string) int {
 CheckFlags:
        for _, flag := range gcflags {
                // Concurrent compilation is presumed incompatible with any gcflags,
-               // except for a small whitelist of commonly used flags.
+               // except for known commonly used flags.
                // If the user knows better, they can manually add their own -c to the gcflags.
                switch flag {
                case "-N", "-l", "-S", "-B", "-C", "-I":
index 8214488a59a6cc05bb7e1f4bfbb6f3fbe55e30e7..2a4d2935b3853011b4d967cce519df364188799d 100644 (file)
@@ -174,6 +174,25 @@ func proxyHandler(w http.ResponseWriter, r *http.Request) {
                return
        }
 
+       // Request for $GOPROXY/redirect/<count>/... goes to redirects.
+       if strings.HasPrefix(path, "redirect/") {
+               path = path[len("redirect/"):]
+               if j := strings.Index(path, "/"); j >= 0 {
+                       count, err := strconv.Atoi(path[:j])
+                       if err != nil {
+                               return
+                       }
+
+                       // The last redirect.
+                       if count <= 1 {
+                               http.Redirect(w, r, fmt.Sprintf("/mod/%s", path[j+1:]), 302)
+                               return
+                       }
+                       http.Redirect(w, r, fmt.Sprintf("/mod/redirect/%d/%s", count-1, path[j+1:]), 302)
+                       return
+               }
+       }
+
        // Request for $GOPROXY/sumdb/<name>/supported
        // is checking whether it's OK to access sumdb via the proxy.
        if path == "sumdb/"+testSumDBName+"/supported" {
index a49a705fa60042cf68aed2334f4a753e11b7fe34..2e8f18a897222c6d58157817d20143bd01c3e967 100644 (file)
@@ -130,6 +130,7 @@ func (ts *testScript) setup() {
                "GOPROXY=" + proxyURL,
                "GOPRIVATE=",
                "GOROOT=" + testGOROOT,
+               "GOROOT_FINAL=" + os.Getenv("GOROOT_FINAL"), // causes spurious rebuilds and breaks the "stale" built-in if not propagated
                "TESTGO_GOROOT=" + testGOROOT,
                "GOSUMDB=" + testSumDBVerifierKey,
                "GONOPROXY=",
index c7fa7cfef5c7a1a8356f06fdac7e1938929b077a..76d665171830f2843fb172b7fee5244ab456cbc7 100644 (file)
@@ -34,6 +34,7 @@ Scripts also have access to these other environment variables:
        GOPATH=$WORK/gopath
        GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
        GOROOT=<actual GOROOT>
+       GOROOT_FINAL=<actual GOROOT_FINAL>
        TESTGO_GOROOT=<GOROOT used to build cmd/go, for use in tests that may change GOROOT>
        HOME=/no-home
        PATH=<actual PATH>
index cfab80743eabd42a5f2235bbb985e482e29bc085..ad78bcf2b27718e54554ab00421c3462c474d72d 100644 (file)
@@ -1,5 +1,9 @@
 [short] skip
 
+# If GOROOT_FINAL is set, 'go build -trimpath' bakes that into the resulting
+# binary instead of GOROOT. Explicitly unset it here.
+env GOROOT_FINAL=
+
 # Set up two identical directories that can be used as GOPATH.
 env GO111MODULE=on
 mkdir $WORK/a/src/paths $WORK/b/src/paths
index 4e04bad69b46b795dd5993d3ac2f868f2e11abfa..fdbcde06cbcee181b1d832d4bd6463e269167145 100644 (file)
@@ -2,6 +2,13 @@
 
 mkdir $WORK/new/bin
 
+# In this test, we are specifically checking the logic for deriving
+# the value of GOROOT from runtime.GOROOT.
+# GOROOT_FINAL changes the default behavior of runtime.GOROOT,
+# and will thus cause the test to fail if it is set when our
+# new cmd/go is built.
+env GOROOT_FINAL=
+
 go build -o $WORK/new/bin/go$GOEXE cmd/go &
 go build -o $WORK/bin/check$GOEXE check.go &
 wait
index 267c90eb3ce07daad555058fca144dddf6e46726..ad22aca5be8ddcbec02af74e728adf6a199ec3cb 100644 (file)
@@ -20,7 +20,6 @@ cd $WORK/gopkgdir/x
 ! go list .
 stderr 'cannot find main module'
 ! stderr 'Gopkg.lock'
-! stderr 'go mod init'
 
 -- $WORK/test/Gopkg.lock --
 -- $WORK/test/x/x.go --
diff --git a/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt b/src/cmd/go/testdata/script/mod_get_too_many_redirects.txt
new file mode 100644 (file)
index 0000000..9cbe0d2
--- /dev/null
@@ -0,0 +1,10 @@
+env GO111MODULE=on
+env GOPROXYBASE=$GOPROXY
+env GOPROXY=$GOPROXYBASE/redirect/11
+env GOSUMDB=off
+
+! go get -d rsc.io/quote@v1.2.0
+stderr 'stopped after 10 redirects'
+
+env GOPROXY=$GOPROXYBASE/redirect/9
+go get -d rsc.io/quote@v1.2.0
index 5d73edd318f7c59203e892261607ccaf3052a4c9..2e6167322e783af9cdfc47d536b3a1293a244b6a 100644 (file)
@@ -36,7 +36,7 @@ func findGorootModules(t *testing.T) []gorootModule {
                        if err != nil {
                                return err
                        }
-                       if info.Name() == "vendor" || info.Name() == "testdata" {
+                       if info.IsDir() && (info.Name() == "vendor" || info.Name() == "testdata") {
                                return filepath.SkipDir
                        }
                        if path == filepath.Join(runtime.GOROOT(), "pkg") {
index 7f5cba645a8b9e6dc18a64a7c45e29b667bd8551..df17729a7650f58171644758f2f00da6f71ca289 100644 (file)
@@ -460,7 +460,6 @@ var optab = []Optab{
        {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
        {ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
        {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
-       {AVCNT, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0},
        {AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0},
        {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
        {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
@@ -2773,6 +2772,7 @@ func buildop(ctxt *obj.Link) {
                        oprangeset(AVSRI, t)
 
                case AVREV32:
+                       oprangeset(AVCNT, t)
                        oprangeset(AVRBIT, t)
                        oprangeset(AVREV64, t)
                        oprangeset(AVREV16, t)
@@ -4523,7 +4523,7 @@ func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
                        c.ctxt.Diag("invalid arrangement: %v\n", p)
                }
 
-               if (p.As == AVMOV || p.As == AVRBIT) && (af != ARNG_16B && af != ARNG_8B) {
+               if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
                        c.ctxt.Diag("invalid arrangement: %v", p)
                }
 
index 2f94ec6a67d99f9df35a8d51fd1e923240389496..f7873a42b9d6d03b1f7f4f3b3000ae38d079b05a 100644 (file)
@@ -134,7 +134,7 @@ func init() {
 }
 
 func Framepointer_enabled(goos, goarch string) bool {
-       return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && goos == "linux")
+       return framepointer_enabled != 0 && (goarch == "amd64" || goarch == "arm64" && (goos == "linux" || goos == "darwin"))
 }
 
 func addexp(s string) {
index 326f493e2dd6254ce435fb1894c4cf607865e662..ac6937ced02725a474e2b2b4f41d48d1681ca6a8 100644 (file)
@@ -33,8 +33,8 @@ func testDWARF(t *testing.T, buildmode string, expectDWARF bool, env ...string)
                t.Fatalf("go list: %v\n%s", err, out)
        }
        if string(out) != "false\n" {
-               if os.Getenv("GOROOT_FINAL_OLD") != "" {
-                       t.Skip("cmd/link is stale, but $GOROOT_FINAL_OLD is set")
+               if strings.HasPrefix(testenv.Builder(), "darwin-") {
+                       t.Skipf("cmd/link is spuriously stale on Darwin builders - see #33598")
                }
                t.Fatalf("cmd/link is stale - run go install cmd/link")
        }
index 9b4214bdca6404909809a9eb30f27a46dbd20378..f87776ef12b210e0034d95423ed67f748215a207 100644 (file)
@@ -616,15 +616,15 @@ func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
        }
        fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason)
 
-       // For the moment, whitelist DWARF subprogram DIEs for
+       // For the moment, allow DWARF subprogram DIEs for
        // auto-generated wrapper functions. What seems to happen
        // here is that we get different line numbers on formal
        // params; I am guessing that the pos is being inherited
        // from the spot where the wrapper is needed.
-       whitelist := strings.HasPrefix(name, "go.info.go.interface") ||
+       allowed := strings.HasPrefix(name, "go.info.go.interface") ||
                strings.HasPrefix(name, "go.info.go.builtin") ||
                strings.HasPrefix(name, "go.debuglines")
-       if !whitelist {
+       if !allowed {
                l.strictDupMsgs++
        }
 }
index c974d6707bc3b4342116fdb539cc1f1e9acb722a..a9dc7d1a5e26c6ef5c661105cdf840e0ef70a2f7 100644 (file)
@@ -138,7 +138,11 @@ func testDisasm(t *testing.T, printCode bool, printGnuAsm bool, flags ...string)
        args = append(args, flags...)
        args = append(args, "fmthello.go")
        cmd := exec.Command(testenv.GoToolPath(t), args...)
-       cmd.Dir = "testdata" // "Bad line" bug #36683 is sensitive to being run in the source directory
+       // "Bad line" bug #36683 is sensitive to being run in the source directory.
+       cmd.Dir = "testdata"
+       // Ensure that the source file location embedded in the binary matches our
+       // actual current GOROOT, instead of GOROOT_FINAL if set.
+       cmd.Env = append(os.Environ(), "GOROOT_FINAL=")
        t.Logf("Running %v", cmd.Args)
        out, err := cmd.CombinedOutput()
        if err != nil {
index fd21ae8fb10e3925b33b47ba8eb76e64e2b50116..3a5ca226133c493121e5a1be001caeac1dedbb8c 100644 (file)
@@ -278,6 +278,8 @@ type ClientSessionState struct {
        serverCertificates []*x509.Certificate   // Certificate chain presented by the server
        verifiedChains     [][]*x509.Certificate // Certificate chains we built for verification
        receivedAt         time.Time             // When the session ticket was received from the server
+       ocspResponse       []byte                // Stapled OCSP response presented by the server
+       scts               [][]byte              // SCTs presented by the server
 
        // TLS 1.3 fields.
        nonce  []byte    // Ticket nonce sent by the server, to derive PSK
index 40c8e02c53dc7f980581f66b755e38dddf4fbaf5..46b0a770d5309436660038f77b3f6d08e32eaa60 100644 (file)
@@ -728,10 +728,17 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
                return false, errors.New("tls: server resumed a session with a different cipher suite")
        }
 
-       // Restore masterSecret and peerCerts from previous state
+       // Restore masterSecret, peerCerts, and ocspResponse from previous state
        hs.masterSecret = hs.session.masterSecret
        c.peerCertificates = hs.session.serverCertificates
        c.verifiedChains = hs.session.verifiedChains
+       c.ocspResponse = hs.session.ocspResponse
+       // Let the ServerHello SCTs override the session SCTs from the original
+       // connection, if any are provided
+       if len(c.scts) == 0 && len(hs.session.scts) != 0 {
+               c.scts = hs.session.scts
+       }
+
        return true, nil
 }
 
@@ -788,6 +795,8 @@ func (hs *clientHandshakeState) readSessionTicket() error {
                serverCertificates: c.peerCertificates,
                verifiedChains:     c.verifiedChains,
                receivedAt:         c.config.time(),
+               ocspResponse:       c.ocspResponse,
+               scts:               c.scts,
        }
 
        return nil
index 1cda90190cec2e7e3533199bb4dcae85b8b84248..12b0254123e938a71dd6b8c0592db9cf235bf255 100644 (file)
@@ -19,6 +19,7 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "reflect"
        "strconv"
        "strings"
        "testing"
@@ -2430,3 +2431,83 @@ func TestDowngradeCanary(t *testing.T) {
                t.Errorf("client unexpectedly reacted to a canary in TLS 1.0")
        }
 }
+
+func TestResumptionKeepsOCSPAndSCT(t *testing.T) {
+       t.Run("TLSv12", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS12) })
+       t.Run("TLSv13", func(t *testing.T) { testResumptionKeepsOCSPAndSCT(t, VersionTLS13) })
+}
+
+func testResumptionKeepsOCSPAndSCT(t *testing.T, ver uint16) {
+       issuer, err := x509.ParseCertificate(testRSACertificateIssuer)
+       if err != nil {
+               t.Fatalf("failed to parse test issuer")
+       }
+       roots := x509.NewCertPool()
+       roots.AddCert(issuer)
+       clientConfig := &Config{
+               MaxVersion:         ver,
+               ClientSessionCache: NewLRUClientSessionCache(32),
+               ServerName:         "example.golang",
+               RootCAs:            roots,
+       }
+       serverConfig := testConfig.Clone()
+       serverConfig.MaxVersion = ver
+       serverConfig.Certificates[0].OCSPStaple = []byte{1, 2, 3}
+       serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{4, 5, 6}}
+
+       _, ccs, err := testHandshake(t, clientConfig, serverConfig)
+       if err != nil {
+               t.Fatalf("handshake failed: %s", err)
+       }
+       // after a new session we expect to see OCSPResponse and
+       // SignedCertificateTimestamps populated as usual
+       if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) {
+               t.Errorf("client ConnectionState contained unexpected OCSPResponse: wanted %v, got %v",
+                       serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse)
+       }
+       if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) {
+               t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps: wanted %v, got %v",
+                       serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
+       }
+
+       // if the server doesn't send any SCTs, repopulate the old SCTs
+       oldSCTs := serverConfig.Certificates[0].SignedCertificateTimestamps
+       serverConfig.Certificates[0].SignedCertificateTimestamps = nil
+       _, ccs, err = testHandshake(t, clientConfig, serverConfig)
+       if err != nil {
+               t.Fatalf("handshake failed: %s", err)
+       }
+       if !ccs.DidResume {
+               t.Fatalf("expected session to be resumed")
+       }
+       // after a resumed session we also expect to see OCSPResponse
+       // and SignedCertificateTimestamps populated
+       if !bytes.Equal(ccs.OCSPResponse, serverConfig.Certificates[0].OCSPStaple) {
+               t.Errorf("client ConnectionState contained unexpected OCSPResponse after resumption: wanted %v, got %v",
+                       serverConfig.Certificates[0].OCSPStaple, ccs.OCSPResponse)
+       }
+       if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, oldSCTs) {
+               t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v",
+                       oldSCTs, ccs.SignedCertificateTimestamps)
+       }
+
+       //  Only test overriding the SCTs for TLS 1.2, since in 1.3
+       // the server won't send the message containing them
+       if ver == VersionTLS13 {
+               return
+       }
+
+       // if the server changes the SCTs it sends, they should override the saved SCTs
+       serverConfig.Certificates[0].SignedCertificateTimestamps = [][]byte{{7, 8, 9}}
+       _, ccs, err = testHandshake(t, clientConfig, serverConfig)
+       if err != nil {
+               t.Fatalf("handshake failed: %s", err)
+       }
+       if !ccs.DidResume {
+               t.Fatalf("expected session to be resumed")
+       }
+       if !reflect.DeepEqual(ccs.SignedCertificateTimestamps, serverConfig.Certificates[0].SignedCertificateTimestamps) {
+               t.Errorf("client ConnectionState contained unexpected SignedCertificateTimestamps after resumption: wanted %v, got %v",
+                       serverConfig.Certificates[0].SignedCertificateTimestamps, ccs.SignedCertificateTimestamps)
+       }
+}
index 35a00f2f3a4c87376f9cdc8e2518541eb721f6f6..9c61105cf73d02b18b3c110c15777146d515677b 100644 (file)
@@ -334,6 +334,8 @@ func (hs *clientHandshakeStateTLS13) processServerHello() error {
        c.didResume = true
        c.peerCertificates = hs.session.serverCertificates
        c.verifiedChains = hs.session.verifiedChains
+       c.ocspResponse = hs.session.ocspResponse
+       c.scts = hs.session.scts
        return nil
 }
 
@@ -666,6 +668,8 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error {
                nonce:              msg.nonce,
                useBy:              c.config.time().Add(lifetime),
                ageAdd:             msg.ageAdd,
+               ocspResponse:       c.ocspResponse,
+               scts:               c.scts,
        }
 
        cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
index 288c9c666fa10cbaf6f64eef127d00b9f9e7bb7d..338b48861c92e06604c5579d3e3919dfafc1ed94 100644 (file)
@@ -2129,16 +2129,13 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
                authorityKeyId = parent.SubjectKeyId
        }
 
-       encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
-       pki := publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey}
        subjectKeyId := template.SubjectKeyId
        if len(subjectKeyId) == 0 && template.IsCA {
-               // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2
-               b, err := asn1.Marshal(pki)
-               if err != nil {
-                       return nil, err
-               }
-               h := sha1.Sum(b)
+               // SubjectKeyId generated using method 1 in RFC 5280, Section 4.2.1.2:
+               //   (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
+               //   value of the BIT STRING subjectPublicKey (excluding the tag,
+               //   length, and number of unused bits).
+               h := sha1.Sum(publicKeyBytes)
                subjectKeyId = h[:]
        }
 
@@ -2147,6 +2144,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
                return
        }
 
+       encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
        c := tbsCertificate{
                Version:            2,
                SerialNumber:       template.SerialNumber,
@@ -2154,7 +2152,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
                Issuer:             asn1.RawValue{FullBytes: asn1Issuer},
                Validity:           validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
                Subject:            asn1.RawValue{FullBytes: asn1Subject},
-               PublicKey:          pki,
+               PublicKey:          publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
                Extensions:         extensions,
        }
 
index daef27c8b9dc86be5e83e0f143e727813a1f068b..90bb3a9bc11554e60163d9b59f4989c8d757a554 100644 (file)
@@ -20,6 +20,7 @@ import (
        "path/filepath"
        "strings"
        "sync"
+       _ "unsafe" // for go:linkname
 )
 
 // An Importer provides the context for importing packages from source code.
@@ -133,7 +134,7 @@ func (p *Importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*type
                        // build.Context's VFS.
                        conf.FakeImportC = true
                } else {
-                       conf.UsesCgo = true
+                       setUsesCgo(&conf)
                        file, err := p.cgo(bp)
                        if err != nil {
                                return nil, err
@@ -260,3 +261,6 @@ func (p *Importer) joinPath(elem ...string) string {
        }
        return filepath.Join(elem...)
 }
+
+//go:linkname setUsesCgo go/types.srcimporter_setUsesCgo
+func setUsesCgo(conf *types.Config)
index 7787b88906e3586fd1524d728bfbe3fee56fb6a4..1abcd9d9512271a9b4813358045a0f44dc50dc44 100644 (file)
@@ -105,14 +105,14 @@ type Config struct {
        //          Do not use casually!
        FakeImportC bool
 
-       // If UsesCgo is set, the type checker expects the
+       // If go115UsesCgo is set, the type checker expects the
        // _cgo_gotypes.go file generated by running cmd/cgo to be
        // provided as a package source file. Qualified identifiers
        // referring to package C will be resolved to cgo-provided
        // declarations within _cgo_gotypes.go.
        //
-       // It is an error to set both FakeImportC and UsesCgo.
-       UsesCgo bool
+       // It is an error to set both FakeImportC and go115UsesCgo.
+       go115UsesCgo bool
 
        // If Error != nil, it is called with each error found
        // during type checking; err has dynamic type Error.
@@ -140,6 +140,10 @@ type Config struct {
        DisableUnusedImportCheck bool
 }
 
+func srcimporter_setUsesCgo(conf *Config) {
+       conf.go115UsesCgo = true
+}
+
 // Info holds result type information for a type-checked package.
 // Only the information for which a map is provided is collected.
 // If the package has type errors, the collected information may
index a94770ffef3ed67b3f9e352e4e8ee03836252a75..007babdf9d67aca2c309be73e84519de444ca0d1 100644 (file)
@@ -248,10 +248,10 @@ func (check *Checker) handleBailout(err *error) {
 // Files checks the provided files as part of the checker's package.
 func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(files) }
 
-var errBadCgo = errors.New("cannot use FakeImportC and UsesCgo together")
+var errBadCgo = errors.New("cannot use FakeImportC and go115UsesCgo together")
 
 func (check *Checker) checkFiles(files []*ast.File) (err error) {
-       if check.conf.FakeImportC && check.conf.UsesCgo {
+       if check.conf.FakeImportC && check.conf.go115UsesCgo {
                return errBadCgo
        }
 
index f80b4ec7841f17d79c2c9ced9b6581c44e02645a..078adc5ec7808e02320f073d51c8eed0583cccc4 100644 (file)
@@ -141,10 +141,10 @@ func (check *Checker) importPackage(pos token.Pos, path, dir string) *Package {
        }
 
        // no package yet => import it
-       if path == "C" && (check.conf.FakeImportC || check.conf.UsesCgo) {
+       if path == "C" && (check.conf.FakeImportC || check.conf.go115UsesCgo) {
                imp = NewPackage("C", "C")
                imp.fake = true // package scope is not populated
-               imp.cgo = check.conf.UsesCgo
+               imp.cgo = check.conf.go115UsesCgo
        } else {
                // ordinary import
                var err error
index 13a0cd043607d48d738a53a73c434f61528b707a..356b8298ae36df752fa9f70f67ab97d0c220f6e0 100644 (file)
@@ -240,8 +240,7 @@ func htmlNameFilter(args ...interface{}) string {
        }
        s = strings.ToLower(s)
        if t := attrType(s); t != contentTypePlain {
-               // TODO: Split attr and element name part filters so we can whitelist
-               // attributes.
+               // TODO: Split attr and element name part filters so we can recognize known attributes.
                return filterFailsafe
        }
        for _, r := range s {
index 85c79bbebb3df42a78ea9ea16c27edd2306bcde3..4872fa98511c675142b47677e996979fd9a422ec 100644 (file)
@@ -479,7 +479,7 @@ func DupCloseOnExec(fd int) (int, string, error) {
        return dupCloseOnExecOld(fd)
 }
 
-// dupCloseOnExecUnixOld is the traditional way to dup an fd and
+// dupCloseOnExecOld is the traditional way to dup an fd and
 // set its O_CLOEXEC bit, using two system calls.
 func dupCloseOnExecOld(fd int) (int, string, error) {
        syscall.ForkLock.RLock()
index f7955ec88a9488c3bb893be9592ab1b8a337faae..277a34d5d7a0e2912e4d4144ad353df1881d00c4 100644 (file)
-:: Copyright 2012 The Go Authors. All rights reserved.
-:: Use of this source code is governed by a BSD-style
-:: license that can be found in the LICENSE file.
-
-:: Environment variables that control make.bat:
-::
-:: GOROOT_FINAL: The expected final Go root, baked into binaries.
-:: The default is the location of the Go tree during the build.
-::
-:: GOHOSTARCH: The architecture for host tools (compilers and
-:: binaries).  Binaries of this type must be executable on the current
-:: system, so the only common reason to set this is to set
-:: GOHOSTARCH=386 on an amd64 machine.
-::
-:: GOARCH: The target architecture for installed packages and tools.
-::
-:: GOOS: The target operating system for installed packages and tools.
-::
-:: GO_GCFLAGS: Additional go tool compile arguments to use when
-:: building the packages and commands.
-::
-:: GO_LDFLAGS: Additional go tool link arguments to use when
-:: building the commands.
-::
-:: CGO_ENABLED: Controls cgo usage during the build. Set it to 1
-:: to include all cgo related files, .c and .go file with "cgo"
-:: build directive, in the build. Set it to 0 to ignore them.
-::
-:: CC: Command line to run to compile C code for GOHOSTARCH.
-:: Default is "gcc".
-::
-:: CC_FOR_TARGET: Command line to run compile C code for GOARCH.
-:: This is used by cgo. Default is CC.
-::
-:: FC: Command line to run to compile Fortran code.
-:: This is used by cgo. Default is "gfortran".
-
-@echo off
-
-:: Keep environment variables within this script
-:: unless invoked with --no-local.
-if x%1==x--no-local goto nolocal
-if x%2==x--no-local goto nolocal
-if x%3==x--no-local goto nolocal
-if x%4==x--no-local goto nolocal
-setlocal
-:nolocal
-
-set GOENV=off
-set GOBUILDFAIL=0
-set GOFLAGS=
-set GO111MODULE=
-
-if exist make.bat goto ok
-echo Must run make.bat from Go src directory.
-goto fail
-:ok
-
-:: Clean old generated file that will cause problems in the build.
-del /F ".\pkg\runtime\runtime_defs.go" 2>NUL
-
-:: Set GOROOT for build.
-cd ..
-set GOROOT_TEMP=%CD%
-set GOROOT=
-cd src
-set vflag=
-if x%1==x-v set vflag=-v
-if x%2==x-v set vflag=-v
-if x%3==x-v set vflag=-v
-if x%4==x-v set vflag=-v
-
-if not exist ..\bin\tool mkdir ..\bin\tool
-
-:: Calculating GOROOT_BOOTSTRAP
-if not "x%GOROOT_BOOTSTRAP%"=="x" goto bootstrapset
-for /f "tokens=*" %%g in ('where go 2^>nul') do (
-       if "x%GOROOT_BOOTSTRAP%"=="x" (
-               for /f "tokens=*" %%i in ('%%g env GOROOT 2^>nul') do (
-                       if /I not %%i==%GOROOT_TEMP% (
-                               set GOROOT_BOOTSTRAP=%%i
-                       )
-               )
-       )
-)
-if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4
-
-:bootstrapset
-if not exist "%GOROOT_BOOTSTRAP%\bin\go.exe" goto bootstrapfail
-set GOROOT=%GOROOT_TEMP%
-set GOROOT_TEMP=
-
-echo Building Go cmd/dist using %GOROOT_BOOTSTRAP%
-if x%vflag==x-v echo cmd/dist
-setlocal
-set GOROOT=%GOROOT_BOOTSTRAP%
-set GOOS=
-set GOARCH=
-set GOBIN=
-set GO111MODULE=off
-"%GOROOT_BOOTSTRAP%\bin\go.exe" build -o cmd\dist\dist.exe .\cmd\dist
-endlocal
-if errorlevel 1 goto fail
-.\cmd\dist\dist.exe env -w -p >env.bat
-if errorlevel 1 goto fail
-call env.bat
-del env.bat
-if x%vflag==x-v echo.
-
-if x%1==x--dist-tool goto copydist
-if x%2==x--dist-tool goto copydist
-if x%3==x--dist-tool goto copydist
-if x%4==x--dist-tool goto copydist
-
-set buildall=-a
-if x%1==x--no-clean set buildall=
-if x%2==x--no-clean set buildall=
-if x%3==x--no-clean set buildall=
-if x%4==x--no-clean set buildall=
-if x%1==x--no-banner set buildall=%buildall% --no-banner
-if x%2==x--no-banner set buildall=%buildall% --no-banner
-if x%3==x--no-banner set buildall=%buildall% --no-banner
-if x%4==x--no-banner set buildall=%buildall% --no-banner
-
-:: Run dist bootstrap to complete make.bash.
-:: Bootstrap installs a proper cmd/dist, built with the new toolchain.
-:: Throw ours, built with Go 1.4, away after bootstrap.
-.\cmd\dist\dist.exe bootstrap %vflag% %buildall%
-if errorlevel 1 goto fail
-del .\cmd\dist\dist.exe
-goto end
-
-:: DO NOT ADD ANY NEW CODE HERE.
-:: The bootstrap+del above are the final step of make.bat.
-:: If something must be added, add it to cmd/dist's cmdbootstrap,
-:: to avoid needing three copies in three different shell languages
-:: (make.bash, make.bat, make.rc).
-
-:copydist
-mkdir "%GOTOOLDIR%" 2>NUL
-copy cmd\dist\dist.exe "%GOTOOLDIR%\"
-goto end
-
-:bootstrapfail
-echo ERROR: Cannot find %GOROOT_BOOTSTRAP%\bin\go.exe
-echo Set GOROOT_BOOTSTRAP to a working Go tree ^>= Go 1.4.
-
-:fail
-set GOBUILDFAIL=1
-if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
-
-:end
-
+:: Copyright 2012 The Go Authors. All rights reserved.\r
+:: Use of this source code is governed by a BSD-style\r
+:: license that can be found in the LICENSE file.\r
+\r
+:: Environment variables that control make.bat:\r
+::\r
+:: GOROOT_FINAL: The expected final Go root, baked into binaries.\r
+:: The default is the location of the Go tree during the build.\r
+::\r
+:: GOHOSTARCH: The architecture for host tools (compilers and\r
+:: binaries).  Binaries of this type must be executable on the current\r
+:: system, so the only common reason to set this is to set\r
+:: GOHOSTARCH=386 on an amd64 machine.\r
+::\r
+:: GOARCH: The target architecture for installed packages and tools.\r
+::\r
+:: GOOS: The target operating system for installed packages and tools.\r
+::\r
+:: GO_GCFLAGS: Additional go tool compile arguments to use when\r
+:: building the packages and commands.\r
+::\r
+:: GO_LDFLAGS: Additional go tool link arguments to use when\r
+:: building the commands.\r
+::\r
+:: CGO_ENABLED: Controls cgo usage during the build. Set it to 1\r
+:: to include all cgo related files, .c and .go file with "cgo"\r
+:: build directive, in the build. Set it to 0 to ignore them.\r
+::\r
+:: CC: Command line to run to compile C code for GOHOSTARCH.\r
+:: Default is "gcc".\r
+::\r
+:: CC_FOR_TARGET: Command line to run compile C code for GOARCH.\r
+:: This is used by cgo. Default is CC.\r
+::\r
+:: FC: Command line to run to compile Fortran code.\r
+:: This is used by cgo. Default is "gfortran".\r
+\r
+@echo off\r
+\r
+:: Keep environment variables within this script\r
+:: unless invoked with --no-local.\r
+if x%1==x--no-local goto nolocal\r
+if x%2==x--no-local goto nolocal\r
+if x%3==x--no-local goto nolocal\r
+if x%4==x--no-local goto nolocal\r
+setlocal\r
+:nolocal\r
+\r
+set GOENV=off\r
+set GOBUILDFAIL=0\r
+set GOFLAGS=\r
+set GO111MODULE=\r
+\r
+if exist make.bat goto ok\r
+echo Must run make.bat from Go src directory.\r
+goto fail\r
+:ok\r
+\r
+:: Clean old generated file that will cause problems in the build.\r
+del /F ".\pkg\runtime\runtime_defs.go" 2>NUL\r
+\r
+:: Set GOROOT for build.\r
+cd ..\r
+set GOROOT_TEMP=%CD%\r
+set GOROOT=\r
+cd src\r
+set vflag=\r
+if x%1==x-v set vflag=-v\r
+if x%2==x-v set vflag=-v\r
+if x%3==x-v set vflag=-v\r
+if x%4==x-v set vflag=-v\r
+\r
+if not exist ..\bin\tool mkdir ..\bin\tool\r
+\r
+:: Calculating GOROOT_BOOTSTRAP\r
+if not "x%GOROOT_BOOTSTRAP%"=="x" goto bootstrapset\r
+for /f "tokens=*" %%g in ('where go 2^>nul') do (\r
+       if "x%GOROOT_BOOTSTRAP%"=="x" (\r
+               for /f "tokens=*" %%i in ('%%g env GOROOT 2^>nul') do (\r
+                       if /I not %%i==%GOROOT_TEMP% (\r
+                               set GOROOT_BOOTSTRAP=%%i\r
+                       )\r
+               )\r
+       )\r
+)\r
+if "x%GOROOT_BOOTSTRAP%"=="x" set GOROOT_BOOTSTRAP=%HOMEDRIVE%%HOMEPATH%\Go1.4\r
+\r
+:bootstrapset\r
+if not exist "%GOROOT_BOOTSTRAP%\bin\go.exe" goto bootstrapfail\r
+set GOROOT=%GOROOT_TEMP%\r
+set GOROOT_TEMP=\r
+\r
+echo Building Go cmd/dist using %GOROOT_BOOTSTRAP%\r
+if x%vflag==x-v echo cmd/dist\r
+setlocal\r
+set GOROOT=%GOROOT_BOOTSTRAP%\r
+set GOOS=\r
+set GOARCH=\r
+set GOBIN=\r
+set GO111MODULE=off\r
+"%GOROOT_BOOTSTRAP%\bin\go.exe" build -o cmd\dist\dist.exe .\cmd\dist\r
+endlocal\r
+if errorlevel 1 goto fail\r
+.\cmd\dist\dist.exe env -w -p >env.bat\r
+if errorlevel 1 goto fail\r
+call env.bat\r
+del env.bat\r
+if x%vflag==x-v echo.\r
+\r
+if x%1==x--dist-tool goto copydist\r
+if x%2==x--dist-tool goto copydist\r
+if x%3==x--dist-tool goto copydist\r
+if x%4==x--dist-tool goto copydist\r
+\r
+set buildall=-a\r
+if x%1==x--no-clean set buildall=\r
+if x%2==x--no-clean set buildall=\r
+if x%3==x--no-clean set buildall=\r
+if x%4==x--no-clean set buildall=\r
+if x%1==x--no-banner set buildall=%buildall% --no-banner\r
+if x%2==x--no-banner set buildall=%buildall% --no-banner\r
+if x%3==x--no-banner set buildall=%buildall% --no-banner\r
+if x%4==x--no-banner set buildall=%buildall% --no-banner\r
+\r
+:: Run dist bootstrap to complete make.bash.\r
+:: Bootstrap installs a proper cmd/dist, built with the new toolchain.\r
+:: Throw ours, built with Go 1.4, away after bootstrap.\r
+.\cmd\dist\dist.exe bootstrap %vflag% %buildall%\r
+if errorlevel 1 goto fail\r
+del .\cmd\dist\dist.exe\r
+goto end\r
+\r
+:: DO NOT ADD ANY NEW CODE HERE.\r
+:: The bootstrap+del above are the final step of make.bat.\r
+:: If something must be added, add it to cmd/dist's cmdbootstrap,\r
+:: to avoid needing three copies in three different shell languages\r
+:: (make.bash, make.bat, make.rc).\r
+\r
+:copydist\r
+mkdir "%GOTOOLDIR%" 2>NUL\r
+copy cmd\dist\dist.exe "%GOTOOLDIR%\"\r
+goto end\r
+\r
+:bootstrapfail\r
+echo ERROR: Cannot find %GOROOT_BOOTSTRAP%\bin\go.exe\r
+echo Set GOROOT_BOOTSTRAP to a working Go tree ^>= Go 1.4.\r
+\r
+:fail\r
+set GOBUILDFAIL=1\r
+if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%\r
+\r
+:end\r
index e924e2a07f90d9b82afd520d6dffe27a19d08031..fe6b60982cd5668230fb9c40ee8e7e87adc4e7d5 100644 (file)
@@ -503,7 +503,7 @@ func valueOrDefault(value, def string) string {
 
 // NOTE: This is not intended to reflect the actual Go version being used.
 // It was changed at the time of Go 1.1 release because the former User-Agent
-// had ended up on a blacklist for some intrusion detection systems.
+// had ended up blocked by some intrusion detection systems.
 // See https://codereview.appspot.com/7532043.
 const defaultUserAgent = "Go-http-client/1.1"
 
index b613c21f16ee290aa2390e04f337311b9fa47f46..a995a50658568f923ebea3ff5395d242eee05fb3 100644 (file)
@@ -1698,9 +1698,9 @@ func (c *conn) closeWriteAndWait() {
        time.Sleep(rstAvoidanceDelay)
 }
 
-// validNextProto reports whether the proto is not a blacklisted ALPN
-// protocol name. Empty and built-in protocol types are blacklisted
-// and can't be overridden with alternate implementations.
+// validNextProto reports whether the proto is a valid ALPN protocol name.
+// Everything is valid except the empty string and built-in protocol types,
+// so that those can't be overridden with alternate implementations.
 func validNextProto(proto string) bool {
        switch proto {
        case "", "http/1.1", "http/1.0":
index b93e2bd56af0dd98603d93d7778d3bcb0e7057c3..f2c00ae0cb6a0ac63fe3e9baf21fb66ed459df9c 100644 (file)
@@ -202,10 +202,8 @@ func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
                        break
                }
 
-               // On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause
-               // open(2) to be restarted for regular files. This is easy to reproduce on
-               // fuse file systems (see https://golang.org/issue/11180).
-               if runtime.GOOS == "darwin" && e == syscall.EINTR {
+               // We have to check EINTR here, per issues 11180 and 39237.
+               if e == syscall.EINTR {
                        continue
                }
 
index e619851f9c8276b43614949471e9ec6efbf08557..37bf1b8f2f6f6114507e4d6f74fde0690dd240a8 100644 (file)
@@ -9,7 +9,6 @@ package os
 import (
        "internal/syscall/unix"
        "io"
-       "runtime"
        "syscall"
 )
 
@@ -178,7 +177,7 @@ func openFdAt(dirfd int, name string) (*File, error) {
                }
 
                // See comment in openFileNolog.
-               if runtime.GOOS == "darwin" && e == syscall.EINTR {
+               if e == syscall.EINTR {
                        continue
                }
 
index fb3ee1ea7a55a031af8ac4c9bf7029e7589da272..f8813ce6becd019f5b2aa3b3c776808915bac9e7 100644 (file)
@@ -40,8 +40,8 @@ func (e *PtyError) Error() string {
 
 func (e *PtyError) Unwrap() error { return e.Errno }
 
-// Open returns a master pty and the name of the linked slave tty.
-func Open() (master *os.File, slave string, err error) {
+// Open returns a control pty and the name of the linked process tty.
+func Open() (pty *os.File, processTTY string, err error) {
        m, err := C.posix_openpt(C.O_RDWR)
        if err != nil {
                return nil, "", ptyError("posix_openpt", err)
@@ -54,6 +54,6 @@ func Open() (master *os.File, slave string, err error) {
                C.close(m)
                return nil, "", ptyError("unlockpt", err)
        }
-       slave = C.GoString(C.ptsname(m))
-       return os.NewFile(uintptr(m), "pty-master"), slave, nil
+       processTTY = C.GoString(C.ptsname(m))
+       return os.NewFile(uintptr(m), "pty"), processTTY, nil
 }
index 849a96ec0ec167b2722b32d7c3edb6004a7decf8..a117221400d86111f58079ff93f3c9f7ad4d0fdc 100644 (file)
@@ -19,7 +19,7 @@ import (
        "io"
        "os"
        "os/exec"
-       "os/signal/internal/pty"
+       ptypkg "os/signal/internal/pty"
        "strconv"
        "strings"
        "sync"
@@ -71,20 +71,20 @@ func TestTerminalSignal(t *testing.T) {
        // The test only fails when using a "slow device," in this
        // case a pseudo-terminal.
 
-       master, sname, err := pty.Open()
+       pty, procTTYName, err := ptypkg.Open()
        if err != nil {
-               ptyErr := err.(*pty.PtyError)
+               ptyErr := err.(*ptypkg.PtyError)
                if ptyErr.FuncName == "posix_openpt" && ptyErr.Errno == syscall.EACCES {
                        t.Skip("posix_openpt failed with EACCES, assuming chroot and skipping")
                }
                t.Fatal(err)
        }
-       defer master.Close()
-       slave, err := os.OpenFile(sname, os.O_RDWR, 0)
+       defer pty.Close()
+       procTTY, err := os.OpenFile(procTTYName, os.O_RDWR, 0)
        if err != nil {
                t.Fatal(err)
        }
-       defer slave.Close()
+       defer procTTY.Close()
 
        // Start an interactive shell.
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
@@ -92,9 +92,9 @@ func TestTerminalSignal(t *testing.T) {
        cmd := exec.CommandContext(ctx, bash, "--norc", "--noprofile", "-i")
        // Clear HISTFILE so that we don't read or clobber the user's bash history.
        cmd.Env = append(os.Environ(), "HISTFILE=")
-       cmd.Stdin = slave
-       cmd.Stdout = slave
-       cmd.Stderr = slave
+       cmd.Stdin = procTTY
+       cmd.Stdout = procTTY
+       cmd.Stderr = procTTY
        cmd.SysProcAttr = &syscall.SysProcAttr{
                Setsid:  true,
                Setctty: true,
@@ -105,21 +105,21 @@ func TestTerminalSignal(t *testing.T) {
                t.Fatal(err)
        }
 
-       if err := slave.Close(); err != nil {
-               t.Errorf("closing slave: %v", err)
+       if err := procTTY.Close(); err != nil {
+               t.Errorf("closing procTTY: %v", err)
        }
 
        progReady := make(chan bool)
        sawPrompt := make(chan bool, 10)
        const prompt = "prompt> "
 
-       // Read data from master in the background.
+       // Read data from pty in the background.
        var wg sync.WaitGroup
        wg.Add(1)
        defer wg.Wait()
        go func() {
                defer wg.Done()
-               input := bufio.NewReader(master)
+               input := bufio.NewReader(pty)
                var line, handled []byte
                for {
                        b, err := input.ReadByte()
@@ -130,11 +130,11 @@ func TestTerminalSignal(t *testing.T) {
                                if perr, ok := err.(*os.PathError); ok {
                                        err = perr.Err
                                }
-                               // EOF means master is closed.
+                               // EOF means pty is closed.
                                // EIO means child process is done.
-                               // "file already closed" means deferred close of master has happened.
+                               // "file already closed" means deferred close of pty has happened.
                                if err != io.EOF && err != syscall.EIO && !strings.Contains(err.Error(), "file already closed") {
-                                       t.Logf("error reading from master: %v", err)
+                                       t.Logf("error reading from pty: %v", err)
                                }
                                return
                        }
@@ -161,7 +161,7 @@ func TestTerminalSignal(t *testing.T) {
        }()
 
        // Set the bash prompt so that we can see it.
-       if _, err := master.Write([]byte("PS1='" + prompt + "'\n")); err != nil {
+       if _, err := pty.Write([]byte("PS1='" + prompt + "'\n")); err != nil {
                t.Fatalf("setting prompt: %v", err)
        }
        select {
@@ -172,7 +172,7 @@ func TestTerminalSignal(t *testing.T) {
 
        // Start a small program that reads from stdin
        // (namely the code at the top of this function).
-       if _, err := master.Write([]byte("GO_TEST_TERMINAL_SIGNALS=1 " + os.Args[0] + " -test.run=TestTerminalSignal\n")); err != nil {
+       if _, err := pty.Write([]byte("GO_TEST_TERMINAL_SIGNALS=1 " + os.Args[0] + " -test.run=TestTerminalSignal\n")); err != nil {
                t.Fatal(err)
        }
 
@@ -190,7 +190,7 @@ func TestTerminalSignal(t *testing.T) {
        time.Sleep(pause)
 
        // Send a ^Z to stop the program.
-       if _, err := master.Write([]byte{26}); err != nil {
+       if _, err := pty.Write([]byte{26}); err != nil {
                t.Fatalf("writing ^Z to pty: %v", err)
        }
 
@@ -202,7 +202,7 @@ func TestTerminalSignal(t *testing.T) {
        }
 
        // Restart the stopped program.
-       if _, err := master.Write([]byte("fg\n")); err != nil {
+       if _, err := pty.Write([]byte("fg\n")); err != nil {
                t.Fatalf("writing %q to pty: %v", "fg", err)
        }
 
@@ -217,7 +217,7 @@ func TestTerminalSignal(t *testing.T) {
 
        // Write some data for the program to read,
        // which should cause it to exit.
-       if _, err := master.Write([]byte{'\n'}); err != nil {
+       if _, err := pty.Write([]byte{'\n'}); err != nil {
                t.Fatalf("writing %q to pty: %v", "\n", err)
        }
 
@@ -229,7 +229,7 @@ func TestTerminalSignal(t *testing.T) {
        }
 
        // Exit the shell with the program's exit status.
-       if _, err := master.Write([]byte("exit $?\n")); err != nil {
+       if _, err := pty.Write([]byte("exit $?\n")); err != nil {
                t.Fatalf("writing %q to pty: %v", "exit", err)
        }
 
index d26f3180a3c352611c77a4ed8a9454a6437f1548..8f0355612cb3f3d5b065ae41a3ea9a6a39fb60ca 100644 (file)
@@ -1,51 +1,51 @@
-:: Copyright 2013 The Go Authors. All rights reserved.
-:: Use of this source code is governed by a BSD-style
-:: license that can be found in the LICENSE file.
-
-:: race.bash tests the standard library under the race detector.
-:: https://golang.org/doc/articles/race_detector.html
-
-@echo off
-
-setlocal
-
-if exist make.bat goto ok
-echo race.bat must be run from go\src
-:: cannot exit: would kill parent command interpreter
-goto end
-:ok
-
-set GOROOT=%CD%\..
-call make.bat --dist-tool >NUL
-if errorlevel 1 goto fail
-.\cmd\dist\dist.exe env -w -p >env.bat
-if errorlevel 1 goto fail
-call env.bat
-del env.bat
-
-if %GOHOSTARCH% == amd64 goto continue
-echo Race detector is only supported on windows/amd64.
-goto fail
-
-:continue
-call make.bat --no-banner --no-local
-if %GOBUILDFAIL%==1 goto end
-echo # go install -race std
-go install -race std
-if errorlevel 1 goto fail
-
-go tool dist test -race
-
-if errorlevel 1 goto fail
-goto succ
-
-:fail
-set GOBUILDFAIL=1
-echo Fail.
-goto end
-
-:succ
-echo All tests passed.
-
-:end
-if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%
+:: Copyright 2013 The Go Authors. All rights reserved.\r
+:: Use of this source code is governed by a BSD-style\r
+:: license that can be found in the LICENSE file.\r
+\r
+:: race.bash tests the standard library under the race detector.\r
+:: https://golang.org/doc/articles/race_detector.html\r
+\r
+@echo off\r
+\r
+setlocal\r
+\r
+if exist make.bat goto ok\r
+echo race.bat must be run from go\src\r
+:: cannot exit: would kill parent command interpreter\r
+goto end\r
+:ok\r
+\r
+set GOROOT=%CD%\..\r
+call make.bat --dist-tool >NUL\r
+if errorlevel 1 goto fail\r
+.\cmd\dist\dist.exe env -w -p >env.bat\r
+if errorlevel 1 goto fail\r
+call env.bat\r
+del env.bat\r
+\r
+if %GOHOSTARCH% == amd64 goto continue\r
+echo Race detector is only supported on windows/amd64.\r
+goto fail\r
+\r
+:continue\r
+call make.bat --no-banner --no-local\r
+if %GOBUILDFAIL%==1 goto end\r
+echo # go install -race std\r
+go install -race std\r
+if errorlevel 1 goto fail\r
+\r
+go tool dist test -race\r
+\r
+if errorlevel 1 goto fail\r
+goto succ\r
+\r
+:fail\r
+set GOBUILDFAIL=1\r
+echo Fail.\r
+goto end\r
+\r
+:succ\r
+echo All tests passed.\r
+\r
+:end\r
+if x%GOBUILDEXIT%==x1 exit %GOBUILDFAIL%\r
index 69c181854b026a5e942428a7c63d1e12f884140c..c299671c13f31381f997ce1c059d93f94db39369 100644 (file)
@@ -1,59 +1,54 @@
-:: Copyright 2012 The Go Authors. All rights reserved.
-:: Use of this source code is governed by a BSD-style
-:: license that can be found in the LICENSE file.
-
-@echo off
-
-if exist ..\bin\go.exe goto ok
-echo Must run run.bat from Go src directory after installing cmd/go.
-goto fail
-:ok
-
-:: Keep environment variables within this script
-:: unless invoked with --no-local.
-if x%1==x--no-local goto nolocal
-if x%2==x--no-local goto nolocal
-setlocal
-:nolocal
-
-set GOBUILDFAIL=0
-
-:: we disallow local import for non-local packages, if %GOROOT% happens
-:: to be under %GOPATH%, then some tests below will fail
-set GOPATH=
-:: Issue 14340: ignore GOBIN during all.bat.
-set GOBIN=
-set GOFLAGS=
-set GO111MODULE=
-
-rem TODO avoid rebuild if possible
-
-if x%1==x--no-rebuild goto norebuild
-echo ##### Building packages and commands.
-..\bin\go install -a -v std cmd
-if errorlevel 1 goto fail
-echo.
-:norebuild
-
-:: we must unset GOROOT_FINAL before tests, because runtime/debug requires
-:: correct access to source code, so if we have GOROOT_FINAL in effect,
-:: at least runtime/debug test will fail.
-set GOROOT_FINAL=
-
-:: get CGO_ENABLED
-..\bin\go env > env.bat
-if errorlevel 1 goto fail
-call env.bat
-del env.bat
-echo.
-
-..\bin\go tool dist test
-if errorlevel 1 goto fail
-echo.
-
-goto end
-
-:fail
-set GOBUILDFAIL=1
-
-:end
+:: Copyright 2012 The Go Authors. All rights reserved.\r
+:: Use of this source code is governed by a BSD-style\r
+:: license that can be found in the LICENSE file.\r
+\r
+@echo off\r
+\r
+if exist ..\bin\go.exe goto ok\r
+echo Must run run.bat from Go src directory after installing cmd/go.\r
+goto fail\r
+:ok\r
+\r
+:: Keep environment variables within this script\r
+:: unless invoked with --no-local.\r
+if x%1==x--no-local goto nolocal\r
+if x%2==x--no-local goto nolocal\r
+setlocal\r
+:nolocal\r
+\r
+set GOBUILDFAIL=0\r
+\r
+:: we disallow local import for non-local packages, if %GOROOT% happens\r
+:: to be under %GOPATH%, then some tests below will fail\r
+set GOPATH=\r
+:: Issue 14340: ignore GOBIN during all.bat.\r
+set GOBIN=\r
+set GOFLAGS=\r
+set GO111MODULE=\r
+\r
+rem TODO avoid rebuild if possible\r
+\r
+if x%1==x--no-rebuild goto norebuild\r
+echo ##### Building packages and commands.\r
+..\bin\go install -a -v std cmd\r
+if errorlevel 1 goto fail\r
+echo.\r
+:norebuild\r
+\r
+:: get CGO_ENABLED\r
+..\bin\go env > env.bat\r
+if errorlevel 1 goto fail\r
+call env.bat\r
+del env.bat\r
+echo.\r
+\r
+..\bin\go tool dist test\r
+if errorlevel 1 goto fail\r
+echo.\r
+\r
+goto end\r
+\r
+:fail\r
+set GOBUILDFAIL=1\r
+\r
+:end\r
index bc5e0786d961be889632307440b8287bff377c6b..de634dc9573e5bd96e7fd51e790df6a9cd1f9ee8 100644 (file)
@@ -18,12 +18,12 @@ var _cgo_sigaction unsafe.Pointer
 //go:nosplit
 //go:nowritebarrierrec
 func sigaction(sig uint32, new, old *sigactiont) {
-       // The runtime package is explicitly blacklisted from sanitizer
-       // instrumentation in racewalk.go, but we might be calling into instrumented C
-       // functions here — so we need the pointer parameters to be properly marked.
+       // racewalk.go avoids adding sanitizing instrumentation to package runtime,
+       // but we might be calling into instrumented C functions here,
+       // so we need the pointer parameters to be properly marked.
        //
-       // Mark the input as having been written before the call and the output as
-       // read after.
+       // Mark the input as having been written before the call
+       // and the output as read after.
        if msanenabled && new != nil {
                msanwrite(unsafe.Pointer(new), unsafe.Sizeof(*new))
        }
index 5cbe382ce7aac5e39f5856c3c11f1b151bfa3f65..6c285ec829a30545d35a75bad359e375abb76013 100644 (file)
@@ -61,7 +61,7 @@ func debugCallCheck(pc uintptr) string {
                        "debugCall16384",
                        "debugCall32768",
                        "debugCall65536":
-                       // These functions are whitelisted so that the debugger can initiate multiple function calls.
+                       // These functions are allowed so that the debugger can initiate multiple function calls.
                        // See: https://golang.org/cl/161137/
                        return
                }
index 77a5a387687efa6f3671c08ec34379694514f4a9..eaf8db72208cdc21d7077ccdbfe8302e7eb8a835 100644 (file)
@@ -976,6 +976,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                        throw("malloc called with no P")
                }
        }
+       var span *mspan
        var x unsafe.Pointer
        noscan := typ == nil || typ.ptrdata == 0
        if size <= maxSmallSize {
@@ -1028,10 +1029,10 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                                return x
                        }
                        // Allocate a new maxTinySize block.
-                       span := c.alloc[tinySpanClass]
+                       span = c.alloc[tinySpanClass]
                        v := nextFreeFast(span)
                        if v == 0 {
-                               v, _, shouldhelpgc = c.nextFree(tinySpanClass)
+                               v, span, shouldhelpgc = c.nextFree(tinySpanClass)
                        }
                        x = unsafe.Pointer(v)
                        (*[2]uint64)(x)[0] = 0
@@ -1052,7 +1053,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                        }
                        size = uintptr(class_to_size[sizeclass])
                        spc := makeSpanClass(sizeclass, noscan)
-                       span := c.alloc[spc]
+                       span = c.alloc[spc]
                        v := nextFreeFast(span)
                        if v == 0 {
                                v, span, shouldhelpgc = c.nextFree(spc)
@@ -1063,15 +1064,14 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
                        }
                }
        } else {
-               var s *mspan
                shouldhelpgc = true
                systemstack(func() {
-                       s = largeAlloc(size, needzero, noscan)
+                       span = largeAlloc(size, needzero, noscan)
                })
-               s.freeindex = 1
-               s.allocCount = 1
-               x = unsafe.Pointer(s.base())
-               size = s.elemsize
+               span.freeindex = 1
+               span.allocCount = 1
+               x = unsafe.Pointer(span.base())
+               size = span.elemsize
        }
 
        var scanSize uintptr
@@ -1112,7 +1112,7 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
        // This may be racing with GC so do it atomically if there can be
        // a race marking the bit.
        if gcphase != _GCoff {
-               gcmarknewobject(uintptr(x), size, scanSize)
+               gcmarknewobject(span, uintptr(x), size, scanSize)
        }
 
        if raceenabled {
index dafb4634b4204b1e2b4374b029a5ca13404aed47..fe988c46d9c46ad302127a0a8358bdd4337d913d 100644 (file)
@@ -1627,11 +1627,21 @@ func gcDumpObject(label string, obj, off uintptr) {
 //
 //go:nowritebarrier
 //go:nosplit
-func gcmarknewobject(obj, size, scanSize uintptr) {
+func gcmarknewobject(span *mspan, obj, size, scanSize uintptr) {
        if useCheckmark { // The world should be stopped so this should not happen.
                throw("gcmarknewobject called while doing checkmark")
        }
-       markBitsForAddr(obj).setMarked()
+
+       // Mark object.
+       objIndex := span.objIndex(obj)
+       span.markBitsForIndex(objIndex).setMarked()
+
+       // Mark span.
+       arena, pageIdx, pageMask := pageIndexOf(span.base())
+       if arena.pageMarks[pageIdx]&pageMask == 0 {
+               atomic.Or8(&arena.pageMarks[pageIdx], pageMask)
+       }
+
        gcw := &getg().m.p.ptr().gcw
        gcw.bytesMarked += uint64(size)
        gcw.scanWork += int64(scanSize)
index ba508729c56ae3b82918bba2e37d0846f83ebccf..6a8a34d1edcda7990136cf5e3d2a32ed71970a00 100644 (file)
@@ -529,7 +529,7 @@ func updatememstats() {
 
        // Calculate memory allocator stats.
        // During program execution we only count number of frees and amount of freed memory.
-       // Current number of alive object in the heap and amount of alive heap memory
+       // Current number of alive objects in the heap and amount of alive heap memory
        // are calculated by scanning all spans.
        // Total number of mallocs is calculated as number of frees plus number of alive objects.
        // Similarly, total amount of allocated memory is calculated as amount of freed memory
index f444452bab502abe00a0a9d1adaa8dfd441161a7..632769c11450da7324e45ca3fd084b7fc6752a53 100644 (file)
@@ -296,6 +296,13 @@ func wbBufFlush1(_p_ *p) {
                        continue
                }
                mbits.setMarked()
+
+               // Mark span.
+               arena, pageIdx, pageMask := pageIndexOf(span.base())
+               if arena.pageMarks[pageIdx]&pageMask == 0 {
+                       atomic.Or8(&arena.pageMarks[pageIdx], pageMask)
+               }
+
                if span.spanclass.noscan() {
                        gcw.bytesMarked += uint64(span.elemsize)
                        continue
index ce2ec6dd1db0cd54776e8d78c64b657b5cb226dd..1e86662adc2c8789368e51fef83d13918e955d88 100644 (file)
@@ -563,8 +563,8 @@ func moduledataverify1(datap *moduledata) {
 // given program counter address, or else nil.
 //
 // If pc represents multiple functions because of inlining, it returns
-// the a *Func describing the innermost function, but with an entry
-// of the outermost function.
+// the *Func describing the innermost function, but with an entry of
+// the outermost function.
 func FuncForPC(pc uintptr) *Func {
        f := findfunc(pc)
        if !f.valid() {
index eb2f3317c95cee64acf1ac91974363b71704b2ae..90808573c201903bdb305110fca7c94ab7d4701e 100644 (file)
@@ -253,6 +253,8 @@ func CmpLogicalToZero(a, b, c uint32, d, e uint64) uint64 {
 // 'comparing to zero' expressions
 
 // var + const
+// 'x-const' might be canonicalized to 'x+(-const)', so we check both
+// CMN and CMP for subtraction expressions to make the pattern robust.
 func CmpToZero_ex1(a int64, e int32) int {
        // arm64:`CMN`,-`ADD`,`(BMI|BPL)`
        if a+3 < 0 {
@@ -269,37 +271,41 @@ func CmpToZero_ex1(a int64, e int32) int {
                return 2
        }
 
-       // arm64:`CMP`,-`SUB`,`(BMI|BPL)`
+       // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
        if a-7 < 0 {
                return 3
        }
 
-       // arm64:`CMP`,-`SUB`,`(BMI|BPL)`
+       // arm64:`CMP|CMN`,-`(ADD|SUB)`,`(BMI|BPL)`
        if a-11 >= 0 {
                return 4
        }
 
-       // arm64:`CMP`,-`SUB`,`BEQ`,`(BMI|BPL)`
+       // arm64:`CMP|CMN`,-`(ADD|SUB)`,`BEQ`,`(BMI|BPL)`
        if a-19 > 0 {
                return 4
        }
 
        // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
+       // arm:`CMN`,-`ADD`,`(BMI|BPL)`
        if e+3 < 0 {
                return 5
        }
 
        // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
+       // arm:`CMN`,-`ADD`,`(BMI|BPL)`
        if e+13 >= 0 {
                return 6
        }
 
-       // arm64:`CMPW`,-`SUBW`,`(BMI|BPL)`
+       // arm64:`CMPW|CMNW`,`(BMI|BPL)`
+       // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
        if e-7 < 0 {
                return 7
        }
 
-       // arm64:`CMPW`,-`SUBW`,`(BMI|BPL)`
+       // arm64:`CMPW|CMNW`,`(BMI|BPL)`
+       // arm:`CMP|CMN`, -`(ADD|SUB)`, `(BMI|BPL)`
        if e-11 >= 0 {
                return 8
        }
@@ -326,11 +332,13 @@ func CmpToZero_ex2(a, b, c int64, e, f, g int32) int {
        }
 
        // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
+       // arm:`CMN`,-`ADD`,`(BMI|BPL)`
        if e+f < 0 {
                return 5
        }
 
        // arm64:`CMNW`,-`ADDW`,`(BMI|BPL)`
+       // arm:`CMN`,-`ADD`,`(BMI|BPL)`
        if f+g >= 0 {
                return 6
        }
@@ -350,11 +358,13 @@ func CmpToZero_ex3(a, b, c, d int64, e, f, g, h int32) int {
        }
 
        // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
+       // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
        if e+f*g > 0 {
                return 5
        }
 
        // arm64:`CMNW`,-`MADDW`,`MULW`,`BEQ`,`(BMI|BPL)`
+       // arm:`CMN`,-`MULA`,`MUL`,`BEQ`,`(BMI|BPL)`
        if f+g*h <= 0 {
                return 6
        }
@@ -384,3 +394,16 @@ func CmpToZero_ex4(a, b, c, d int64, e, f, g, h int32) int {
        }
        return 0
 }
+
+func CmpToZero_ex5(e, f int32, u uint32) int {
+       // arm:`CMN`,-`ADD`,`BEQ`,`(BMI|BPL)`
+       if e+f<<1 > 0 {
+               return 1
+       }
+
+       // arm:`CMP`,-`SUB`,`(BMI|BPL)`
+       if f-int32(u>>2) >= 0 {
+               return 2
+       }
+       return 0
+}
diff --git a/test/fixedbugs/issue39472.go b/test/fixedbugs/issue39472.go
new file mode 100644 (file)
index 0000000..61444a2
--- /dev/null
@@ -0,0 +1,12 @@
+// compile -N
+
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+func f(x float64) bool {
+       x += 1
+       return (x != 0) == (x != 0)
+}
index 30e0e3c982e389c56fcfbba114110b2e179c1c1d..c3b48d385cecc8bd1dd4ddfa5e1a8b1377750283 100644 (file)
@@ -4,8 +4,8 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// Check that batch files are maintained as CRLF files (consistent behaviour
-// on all operating systems). See https://github.com/golang/go/issues/37791
+// Check that batch files are maintained as CRLF files (consistent
+// behavior on all operating systems). See golang.org/issue/37791.
 
 package main
 
@@ -13,18 +13,56 @@ import (
        "bytes"
        "fmt"
        "io/ioutil"
+       "log"
        "os"
        "path/filepath"
        "runtime"
+       "strings"
 )
 
 func main() {
-       batches, _ := filepath.Glob(runtime.GOROOT() + "/src/*.bat")
-       for _, bat := range batches {
-               body, _ := ioutil.ReadFile(bat)
-               if !bytes.Contains(body, []byte("\r\n")) {
-                       fmt.Printf("Windows batch file %s does not contain CRLF line termination.\nTry running git checkout src/*.bat to fix this.\n", bat)
-                       os.Exit(1)
+       // Ensure that the GOROOT/src/all.bat file exists and has strict CRLF line endings.
+       enforceBatchStrictCRLF(filepath.Join(runtime.GOROOT(), "src", "all.bat"))
+
+       // Walk the entire Go repository source tree (without GOROOT/pkg),
+       // skipping directories that start with "." and named "testdata",
+       // and ensure all .bat files found have exact CRLF line endings.
+       err := filepath.Walk(runtime.GOROOT(), func(path string, fi os.FileInfo, err error) error {
+               if err != nil {
+                       return err
+               }
+               if fi.IsDir() && (strings.HasPrefix(fi.Name(), ".") || fi.Name() == "testdata") {
+                       return filepath.SkipDir
+               }
+               if path == filepath.Join(runtime.GOROOT(), "pkg") {
+                       // GOROOT/pkg is known to contain generated artifacts, not source code.
+                       // Skip it to avoid false positives. (Also see golang.org/issue/37929.)
+                       return filepath.SkipDir
+               }
+               if filepath.Ext(fi.Name()) == ".bat" {
+                       enforceBatchStrictCRLF(path)
+               }
+               return nil
+       })
+       if err != nil {
+               log.Fatalln(err)
+       }
+}
+
+func enforceBatchStrictCRLF(path string) {
+       b, err := ioutil.ReadFile(path)
+       if err != nil {
+               log.Fatalln(err)
+       }
+       cr, lf := bytes.Count(b, []byte{13}), bytes.Count(b, []byte{10})
+       crlf := bytes.Count(b, []byte{13, 10})
+       if cr != crlf || lf != crlf {
+               if rel, err := filepath.Rel(runtime.GOROOT(), path); err == nil {
+                       // Make the test failure more readable by showing a path relative to GOROOT.
+                       path = rel
                }
+               fmt.Printf("Windows batch file %s does not use strict CRLF line termination.\n", path)
+               fmt.Printf("Please convert it to CRLF before checking it in due to golang.org/issue/37791.\n")
+               os.Exit(1)
        }
 }