[dev.typealias] dev.typealias: merge go1.8.1 into dev.typealias

This also includes fixes since Go 1.8rc3.

a4c18f063b [release-branch.go1.8] go1.8.1
8babce23e3 [release-branch.go1.8] doc: document go1.8.1
853d533ed6 [release-branch.go1.8] cmd/go: add test for test -race -i behavior
166f2159d8 [release-branch.go1.8] cmd/go: do not install broken libraries during 'go test -i -race'
95a5b80e6d [release-branch.go1.8] cmd/compile: added special case for reflect header fields to esc
fe79c75268 [release-branch.go1.8] cmd/compile: add missing WBs for reflect.{Slice,String}Header.Data
d7989b784e [release-branch.go1.8] cmd/link: skip TestDWARF when cgo is disabled
056be9f79c [release-branch.go1.8] cmd/link: skip TestDWARF on Plan 9
02240408a1 [release-branch.go1.8] encoding/xml: disable checking of attribute syntax, like Go 1.7
04017ffadf [release-branch.go1.8] reflect: fix out-of-bounds pointers calling no-result method
2d0043014f [release-branch.go1.8] cmd/link: emit a mach-o dwarf segment that dsymutil will accept
3ca0d34fa1 [release-branch.go1.8] cmd/link: make mach-o dwarf segment properly aligned
84192f2734 [release-branch.go1.8] cmd/link: disable mach-o dwarf munging with -w (in addition to -s)
752b8b773d [release-branch.go1.8] cmd/compile: don't crash when slicing non-slice
ff5695d0fd [release-branch.go1.8] runtime: print user stack on other threads during GOTRACBEACK=crash
517a38c630 [release-branch.go1.8] test/fixedbugs: add test for #19403
dc70a5efd1 [release-branch.go1.8] cmd/compile: mark MOVWF/MOVFW clobbering F15 on ARM
77476e81d9 [release-branch.go1.8] cmd/compile,runtime: fix atomic And8 for mipsle
bf71119d54 [release-branch.go1.8] cmd/compile: repaired loop-finder to handle trickier nesting
11a224bc56 [release-branch.go1.8] cmd/compile: add opcode flag hasSideEffects for do-not-remove
3a8841bcaf [release-branch.go1.8] cmd/link: do not pass -s through to host linker on macOS
6c5abcf21a [release-branch.go1.8] text/template: fix handling of empty blocks
43fa04c23c [release-branch.go1.8] image/png: restore Go 1.7 rejection of transparent gray8 images
e35c01b404 [release-branch.go1.8] net, net/http: adjust time-in-past constant even earlier
c955eb1935 [release-branch.go1.8] cmd/compile/internal/ssa: don't schedule values after select
f8ed4539eb [release-branch.go1.8] os/exec: deflake TestStdinCloseRace
d43130743c [release-branch.go1.8] cmd/link: put plt stubs first in Textp on ppc64x
0a5cec792f [release-branch.go1.8] doc: reorganize the contribution guidelines into a guide
8890527476 [release-branch.go1.8] time: make the ParseInLocation test more robust
ea6781bcd0 [release-branch.go1.8] crypto/tls: make Config.Clone also clone the GetClientCertificate field
2327d696c1 [release-branch.go1.8] cmd/compile: do not fold offset into load/store for args on ARM64
ba48d2002e [release-branch.go1.8] cmd/compile: check both syms when folding address into load/store on ARM64
b43fabfb30 [release-branch.go1.8] cmd/compile: add zero-extension before right shift when lowering Lrot on ARM
6a712dfac1 [release-branch.go1.8] cmd/compile: fix merging of s390x conditional moves into branch conditions
865536b197 [release-branch.go1.8] cmd/compile: remove unnecessary type conversions on s390x
bae53daa72 [release-branch.go1.8] runtime: avoid O(n) semaphore list walk in contention profiling
d4ee1f4a40 [release-branch.go1.8] website: mention go1.8 in project page
991ee8f4ac [release-branch.go1.8] doc: fix broken link in go1.8.html
cd6b6202dd [release-branch.go1.8] go1.8
606eb9b0c1 [release-branch.go1.8] doc: document go1.8
bcda91c18d [release-branch.go1.8] runtime: do not call wakep from enlistWorker, to avoid possible deadlock
7d7a0a9d64 [release-branch.go1.8] doc: update Code of Conduct wording and scope
cedc511a6e [release-branch.go1.8] encoding/xml: fix incorrect indirect code in chardata, comment, innerxml fields
ae13ccfd6d [release-branch.go1.8] database/sql: convert test timeouts to explicit waits with checks
7cec9a583d [release-branch.go1.8] reflect: clear ptrToThis in Ptr when allocating result on heap
d84dee069a [release-branch.go1.8] database/sql: ensure driverConns are closed if not returned to pool
f1e44a4b74 [release-branch.go1.8] database/sql: do not exhaust connection pool on conn request timeout
3ade54063e [release-branch.go1.8] database/sql: record the context error in Rows if canceled
0545006bdb [release-branch.go1.8] crypto/x509: check for new tls-ca-bundle.pem last
1363eeba65 [release-branch.go1.8] cmd/go, go/build: better defenses against GOPATH=GOROOT
1edfd64761 [release-branch.go1.8] cmd/compile: do not use "oaslit" for global
6eb0f5440e [release-branch.go1.8] cmd/compile/internal/syntax: avoid follow-up error for incorrect if statement
c543cc353d [release-branch.go1.8] cmd/compile/internal/syntax: make a parser error "1.7 compliant"
f0749fe163 [release-branch.go1.8] cmd/link: use external linking for PIE by default
ba878ac0c8 [release-branch.go1.8] doc: remove inactive members of the CoC working group
6177f6d448 [release-branch.go1.8] vendor/golang.org/x/crypto/curve25519: avoid loss of R15 in -dynlink mode
67cd1fa780 [release-branch.go1.8] cmd/compile: do not fold large offset on ARM64

Change-Id: I907afba886429c4feb36c9895f16046eeab4ad5f
diff --git a/VERSION b/VERSION
index 5f9fe66..bc75b47 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-go1.8.typealias
\ No newline at end of file
+go1.8.1.typealias
\ No newline at end of file
diff --git a/doc/conduct.html b/doc/conduct.html
index 5b81681..c40b007 100644
--- a/doc/conduct.html
+++ b/doc/conduct.html
@@ -148,29 +148,26 @@
 
 <p>
 The Go spaces are not free speech venues; they are for discussion about Go.
-These spaces have moderators.
-The goal of the moderators is to facilitate civil discussion about Go.
+Each of these spaces have their own moderators.
 </p>
 
 <p>
 When using the official Go spaces you should act in the spirit of the “Gopher
 values”.
-If you conduct yourself in a way that is explicitly forbidden by the CoC,
-you will be warned and asked to stop.
-If you do not stop, you will be removed from our community spaces temporarily.
-Repeated, willful breaches of the CoC will result in a permanent ban.
+If a reported conflict cannot be resolved amicably, the CoC Working Group
+may make a recommendation to the relevant forum moderators.
 </p>
 
 <p>
-Moderators are held to a higher standard than other community members.
-If a moderator creates an inappropriate situation, they should expect less
-leeway than others, and should expect to be removed from their position if they
-cannot adhere to the CoC.
+CoC Working Group members and forum moderators are held to a higher standard than other community members.
+If a working group member or moderator creates an inappropriate situation, they
+should expect less leeway than others, and should expect to be removed from
+their position if they cannot adhere to the CoC.
 </p>
 
 <p>
-Complaints about moderator actions must be handled using the reporting process
-below.
+Complaints about working group member or moderator actions must be handled 
+using the reporting process below.
 </p>
 
 <h2 id="reporting">Reporting issues</h2>
@@ -185,8 +182,6 @@
 <ul>
 	<li>Aditya Mukerjee &lt;dev@chimeracoder.net&gt;
 	<li>Andrew Gerrand &lt;adg@golang.org&gt;
-	<li>Dave Cheney &lt;dave@cheney.net&gt;
-	<li>Jason Buberel &lt;jbuberel@google.com&gt;
 	<li>Peggy Li &lt;peggyli.224@gmail.com&gt;
 	<li>Sarah Adams &lt;sadams.codes@gmail.com&gt;
 	<li>Steve Francia &lt;steve.francia@gmail.com&gt;
@@ -201,13 +196,10 @@
 </p>
 
 <ul>
-<li>Mail <a href="mailto:conduct@golang.org">conduct@golang.org</a> or
-    <a href="https://golang.org/s/conduct-report">submit an anonymous report</a>.
+<li>Mail <a href="mailto:conduct@golang.org">conduct@golang.org</a>.
     <ul>
     <li>Your message will reach the Working Group.
     <li>Reports are confidential within the Working Group.
-    <li>Should you choose to remain anonymous then the Working Group cannot
-        notify you of the outcome of your report.
     <li>You may contact a member of the group directly if you do not feel
         comfortable contacting the group as a whole. That member will then raise
         the issue with the Working Group as a whole, preserving the privacy of the
@@ -229,11 +221,8 @@
 <li>The Working Group will reach a decision as to how to act. These may include:
     <ul>
     <li>Nothing.
-    <li>A request for a private or public apology.
-    <li>A private or public warning.
-    <li>An imposed vacation (for instance, asking someone to abstain for a week
-        from a mailing list or IRC).
-    <li>A permanent or temporary ban from some or all Go spaces.
+    <li>Passing the report along to the offender.
+    <li>A recommendation of action to the relevant forum moderators.
     </ul>
 <li>The Working Group will reach out to the original reporter to let them know
     the decision.
@@ -246,7 +235,6 @@
 conflicts in the most harmonious way possible.</b>
 We hope that in most cases issues may be resolved through polite discussion and
 mutual agreement.
-Bannings and other forceful measures are to be employed only as a last resort.
 </p>
 
 <p>
diff --git a/doc/contrib.html b/doc/contrib.html
index 7bf3d89..fd548d7 100644
--- a/doc/contrib.html
+++ b/doc/contrib.html
@@ -34,6 +34,7 @@
 <p>A <a href="/doc/devel/release.html">summary</a> of the changes between Go releases. Notes for the major releases:</p>
 
 <ul>
+	<li><a href="/doc/go1.8">Go 1.8</a> <small>(February 2017)</small></li>
 	<li><a href="/doc/go1.7">Go 1.7</a> <small>(August 2016)</small></li>
 	<li><a href="/doc/go1.6">Go 1.6</a> <small>(February 2016)</small></li>
 	<li><a href="/doc/go1.5">Go 1.5</a> <small>(August 2015)</small></li>
diff --git a/doc/contribute.html b/doc/contribute.html
index f1a5b27..6977579 100644
--- a/doc/contribute.html
+++ b/doc/contribute.html
@@ -1,14 +1,12 @@
 <!--{
-	"Title": "Contribution Guidelines"
+	"Title": "Contribution Guide"
 }-->
 
-<h2 id="Introduction">Introduction</h2>
-
 <p>
-This document explains how to contribute changes to the Go project.
-It assumes you have followed the
-<a href="/doc/install/source">installation instructions</a> and
-have <a href="code.html">written and tested your code</a>.
+The Go project welcomes all contributors. The process of contributing
+to the Go project may be different than many projects you are used to.
+This document is intended as a guide to help you through the contribution
+process. This guide assumes you have a basic understanding of Git and Go.
 </p>
 
 <p>
@@ -20,103 +18,54 @@
 Sensitive security-related issues should be reported to <a href="mailto:security@golang.org">security@golang.org</a>.
 </p>
 
-<h2 id="Design">Discuss your design</h2>
+<h1 id="contributor">Becoming a contributor</h1>
 
 <p>
-The project welcomes submissions but please let everyone know what
-you're working on if you want to change or add to the Go repositories.
+Before you can contribute to the Go project you need to setup a few prerequisites.
+The Go project uses <a href="https://www.gerritcodereview.com/">Gerrit</a>, an open
+source online tool, to perform all code reviews.
+Gerrit uses your email address as a unique identifier.
+The Go project contributing flow is currently configured to work only with Google Accounts.
+You must go through the following process <em>prior to contributing</em>.
+You only need to do this once per Google Account.
+</p>
+
+<h2 id="auth">Configure Git to use Gerrit</h2>
+<p>
+You'll need a web browser and a command line terminal.
+You should already have Git installed.
 </p>
 
 <p>
-Before undertaking to write something new for the Go project,
-please <a href="https://golang.org/issue/new">file an issue</a>
-(or claim an <a href="https://golang.org/issues">existing issue</a>).
-Significant changes must go through the
-<a href="https://golang.org/s/proposal-process">change proposal process</a>
-before they can be accepted.
-</p>
-
-<p>
-This process gives everyone a chance to validate the design,
-helps prevent duplication of effort,
-and ensures that the idea fits inside the goals for the language and tools.
-It also checks that the design is sound before code is written;
-the code review tool is not the place for high-level discussions.
-</p>
-
-<p>
-When planning work, please note that the Go project follows a
-<a href="https://golang.org/wiki/Go-Release-Cycle">six-month
-development cycle</a>. The latter half of each cycle is a three-month
-feature freeze during which only bug fixes and doc updates are accepted.
-New work cannot be submitted during a feature freeze.
-</p>
-
-<h2 id="Testing">Testing redux</h2>
-
-<p>
-You've <a href="code.html">written and tested your code</a>, but
-before sending code out for review, run all the tests for the whole
-tree to make sure the changes don't break other packages or programs:
-</p>
-
-<pre>
-$ cd go/src
-$ ./all.bash
-</pre>
-
-<p>
-(To build under Windows use <code>all.bat</code>.)
-</p>
-
-<p>
-After running for a while, the command should print
-"<code>ALL</code> <code>TESTS</code> <code>PASSED</code>".
-</p>
-
-<h2 id="Code_review">Code review</h2>
-
-<p>
-Changes to Go must be reviewed before they are accepted,
-no matter who makes the change.
-A custom git command called <code>git-codereview</code>,
-discussed below, helps manage the code review process through a Google-hosted
-<a href="https://go-review.googlesource.com/">instance</a> of the code review
-system called <a href="https://www.gerritcodereview.com/">Gerrit</a>.
-</p>
-
-<h3 id="auth">Set up authentication for code review</h3>
-
-<p>
-Gerrit uses Google Accounts for authentication. If you don't have
-a Google Account, you can create an account which
+Gerrit uses Google Accounts for authentication.
+If you don't have a Google Account, you can create an account which
 <a href="https://www.google.com/accounts/NewAccount">includes
 a new Gmail email account</a> or create an account associated
 <a href="https://accounts.google.com/SignUpWithoutGmail">with your existing
 email address</a>.
 </p>
 
-<p>
-The email address associated with the Google Account you use will be recorded in
-the <a href="https://go.googlesource.com/go/+log/">change log</a>
-and in the <a href="/CONTRIBUTORS">contributors file</a>.
-</p>
+<h3>Step 1: Sign in to googlesource and generate a password</h3>
 
 <p>
-To set up your account in Gerrit, visit
-<a href="https://go.googlesource.com">go.googlesource.com</a>
+Visit <a href="https://go.googlesource.com">go.googlesource.com</a>
 and click on "Generate Password" in the page's top right menu bar.
-</p>
-
-<p>
 You will be redirected to accounts.google.com to sign in.
 </p>
 
+<h3>Step 2: Run the provided script</h3>
 <p>
-Once signed in, you are returned back to go.googlesource.com to "Configure Git".
-Follow the instructions on the page.
-(If you are on a Windows computer, you should instead follow the instructions
-in the yellow box to run the command.)
+After signing in, you are taken to a page on go.googlesource.com with the title "Configure Git".
+This page contains a personalized script which when run locally will configure git
+to have your unique authentication key.
+This key is paired with one generated server side similar to how ssh keys work.
+</p>
+
+<p>
+Copy and run this script locally in your command line terminal.
+(On a Windows computer using cmd you should instead follow the instructions
+in the yellow box to run the command. If you are using git-bash use the same
+script as *nix.)
 </p>
 
 <p>
@@ -124,23 +73,25 @@
 and Git is configured to use this file.
 </p>
 
-<h3 id="gerrit">Register with Gerrit</h3>
+<h3 id="gerrit">Step 3: Register with Gerrit</h3>
 
 <p>
-Now that you have your authentication token,
-you need to register your account with Gerrit.
-To do this, visit
-<a href="https://go-review.googlesource.com/login/">
-go-review.googlesource.com/login/</a>. You will immediately be redirected
-to Google Accounts. Sign in using the same Google Account you used above.
-That is all that is required.
+Now that you have your authentication token, you need to register your
+account with Gerrit.
+To do this, visit <a href="https://go-review.googlesource.com/login/">
+go-review.googlesource.com/login/</a>.
+Sign in using the same Google Account you used above.
 </p>
 
-<h3 id="cla">Contributor License Agreement</h3>
+<h2 id="cla">Contributor License Agreement</h2>
 
-<p>Gerrit serves as the gatekeeper and uses your e-mail address as the key.
-To send your first change to the Go project from a given address,
-you must have completed one of the contributor license agreements:
+<h3 id="which_cla">Which CLA</h3>
+<p>
+Before sending your first change to the Go project
+you must have completed one of the following two CLAs.
+Which CLA you should sign depends on who owns the copyright to your work.
+</p>
+
 <ul>
 <li>
 If you are the copyright holder, you will need to agree to the
@@ -151,37 +102,49 @@
 If your organization is the copyright holder, the organization
 will need to agree to the
 <a href="https://developers.google.com/open-source/cla/corporate">corporate
-contributor license agreement</a>.
-(If the copyright holder for your code has already completed the
-agreement in connection with another Google open source project,
-it does not need to be completed again.)
+contributor license agreement</a>.<br>
 </li>
 </ul>
 
 <p>
-You can use the links above to create and sign the contributor license agreement
-or you can show your current agreements and create new ones through the Gerrit
-interface.  <a href="https://go-review.googlesource.com/login/">Log into Gerrit</a>,
+<i>If the copyright holder for your contribution has already completed the
+agreement in connection with another Google open source project,
+it does not need to be completed again.</i>
+</p>
+
+<h3 id="signing_cla">Completing the CLA</h3>
+
+<p>
+You can see your currently signed agreements and sign new ones through the Gerrit
+interface.
+To do this, <a href="https://go-review.googlesource.com/login/">Log into Gerrit</a>,
 click your name in the upper-right, choose "Settings", then select "Agreements"
-from the topics on the left. If you do not have a signed agreement listed here,
+from the topics on the left.
+If you do not have a signed agreement listed here,
 you can create one by clicking "New Contributor Agreement" and following the steps.
 </p>
 
 <p>
-This rigmarole only needs to be done for your first submission for each email address.
+If the copyright holder for the code you are submitting changes &mdash; for example,
+if you start contributing code on behalf of a new company &mdash; please send email
+to golang-dev and let us know, so that we can make sure an appropriate agreement is
+completed and update the <code>AUTHORS</code> file.
 </p>
 
+<span id="Code_review"></span>
+<h1 id="prepare_dev_env">Preparing a Development Environment for Contributing</h1>
+
+<h2 id="git-codereview">Setting up Git for submission to Gerrit</h2>
 <p>
-If the copyright holder for the code you are submitting changes—for example,
-if you start contributing code on behalf of a new company—please send email
-to let us know, so that we can make sure an appropriate agreement is completed
-and update the <code>AUTHORS</code> file.
+Changes to Go must be reviewed before they are accepted, no matter who makes the change.
+A custom git command called <code>git-codereview</code>, discussed below,
+helps manage the code review process through a Google-hosted
+<a href="https://go-review.googlesource.com/">instance</a> Gerrit.
 </p>
 
-<h3 id="git-codereview">Install the git-codereview command</h3>
-
+<h3 id="git-codereview_install">Install the git-codereview command</h3>
 <p>
-Now install the <code>git-codereview</code> command by running,
+Install the <code>git-codereview</code> command by running,
 </p>
 
 <pre>
@@ -202,18 +165,28 @@
 </p>
 
 <p>
-<b>Note to Git aficionados:</b>
-The <code>git-codereview</code> command is not required to
-upload and manage Gerrit code reviews. For those who prefer plain Git, the text
-below gives the Git equivalent of each git-codereview command.
+On Windows, when using git-bash you must make sure that
+<code>git-codereview.exe</code> is in your git exec-path.
+Run <code>git --exec-path</code> to discover the right location then create a
+symbolic link or simply copy the executible from $GOPATH/bin to this directory.
 </p>
 
-<p>If you do use plain
-Git, note that you still need the commit hooks that the git-codereview command
-configures; those hooks add a Gerrit <code>Change-Id</code> line to the commit
-message and check that all Go source files have been formatted with gofmt. Even
-if you intend to use plain Git for daily work, install the hooks in a new Git
-checkout by running <code>git-codereview</code> <code>hooks</code>.
+<p>
+<b>Note to Git aficionados:</b>
+The <code>git-codereview</code> command is not required to
+upload and manage Gerrit code reviews.
+For those who prefer plain Git, the text below gives the Git equivalent of
+each git-codereview command.
+</p>
+
+<p>
+If you do use plain Git, note that you still need the commit hooks that the
+git-codereview command configures; those hooks add a Gerrit
+<code>Change-Id</code> line to the commit message and check that all Go source
+files have been formatted with gofmt.
+Even if you intend to use plain Git for
+daily work, install the hooks in a new Git checkout by running
+<code>git-codereview</code> <code>hooks</code>.
 </p>
 
 <p>
@@ -264,7 +237,8 @@
 	sync = codereview sync
 </pre>
 
-<h3 id="help">Understanding the git-codereview command</h3>
+<span id="help"></span>
+<h3 id="understanding_git-codereview">Understanding the git-codereview command</h3>
 
 <p>After installing the <code>git-codereview</code> command, you can run</p>
 
@@ -277,11 +251,70 @@
 You can also read the <a href="https://godoc.org/golang.org/x/review/git-codereview">command documentation</a>.
 </p>
 
-<h3 id="master">Switch to the master branch</h3>
+
+<h1 id="making_a_contribution">Making a Contribution</h1>
+
+<h2 id="Design">Discuss your design</h2>
+
+<p>
+The project welcomes submissions but please let everyone know what
+you're working on if you want to change or add to the Go repositories.
+</p>
+
+<p>
+Before undertaking to write something new for the Go project,
+please <a href="https://golang.org/issue/new">file an issue</a>
+(or claim an <a href="https://golang.org/issues">existing issue</a>).
+Significant changes must go through the
+<a href="https://golang.org/s/proposal-process">change proposal process</a>
+before they can be accepted.
+</p>
+
+<p>
+This process gives everyone a chance to validate the design,
+helps prevent duplication of effort,
+and ensures that the idea fits inside the goals for the language and tools.
+It also checks that the design is sound before code is written;
+the code review tool is not the place for high-level discussions.
+</p>
+
+<p>
+When planning work, please note that the Go project follows a <a
+href="https://golang.org/wiki/Go-Release-Cycle">six-month development cycle</a>.
+The latter half of each cycle is a three-month feature freeze during
+which only bug fixes and doc updates are accepted. New contributions can be
+sent during a feature freeze but will not be accepted until the freeze thaws.
+</p>
+
+<h2 id="making_a_change">Making a change</h2>
+
+<h3 id="checkout_go">Getting Go Source</h3>
+<p>
+First you need to have a local copy of the source checked out from the correct
+repository.
+As Go builds Go you will also likely need to have a working version
+of Go installed (some documentation changes may not need this).
+This should be a recent version of Go and can be obtained via any package or
+binary distribution or you can build it from source.
+</p>
+
+<p>
+You should checkout the Go source repo anywhere you want as long as it's
+outside of your $GOPATH.
+Go to a directory where you want the source to appear and run the following
+command in a terminal.
+</p>
+
+<pre><code>
+$ git clone https://go.googlesource.com/go
+$ cd go
+</code></pre>
+
+<h3 id="master">Contributing to the main Go tree</h3>
 
 <p>
 Most Go installations use a release branch, but new changes should
-only be made based on the master branch.
+only be made based on the master branch. <br>
 (They may be applied later to a release branch as part of the release process,
 but most contributors won't do this themselves.)
 Before making a change, make sure you start on the master branch:
@@ -297,10 +330,61 @@
 <code>git</code> <code>pull</code> <code>-r</code>.)
 </p>
 
-<h3 id="change">Make a change</h3>
+<h3 id="subrepos">Contributing to subrepositories (golang.org/x/...)</h3>
 
 <p>
-The entire checked-out tree is writable.
+If you are contributing a change to a subrepository, obtain the
+Go package using <code>go get</code>. For example, to contribute
+to <code>golang.org/x/oauth2</code>, check out the code by running:
+</p>
+
+<pre>
+$ go get -d golang.org/x/oauth2/...
+</pre>
+
+<p>
+Then, change your directory to the package's source directory
+(<code>$GOPATH/src/golang.org/x/oauth2</code>).
+</p>
+
+<h3 id="change">Make your changes</h3>
+
+<p>
+The entire checked-out tree is editable.
+Make your changes as you see fit ensuring that you create appropriate
+tests along with your changes. Test your changes as you go.
+</p>
+
+<h3 id="copyright">Copyright</h3>
+
+<p>
+Files in the Go repository don't list author names, both to avoid clutter
+and to avoid having to keep the lists up to date.
+Instead, your name will appear in the
+<a href="https://golang.org/change">change log</a> and in the <a
+href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file and perhaps the <a
+href="/AUTHORS"><code>AUTHORS</code></a> file.
+These files are automatically generated from the commit logs perodically.
+The <a href="/AUTHORS"><code>AUTHORS</code></a> file defines who &ldquo;The Go
+Authors&rdquo;&mdash;the copyright holders&mdash;are.
+</p>
+
+<p>New files that you contribute should use the standard copyright header:</p>
+
+<pre>
+// Copyright 2017 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.
+</pre>
+
+<p>
+Files in the repository are copyright the year they are added.
+Do not update the copyright year on files that you change.
+</p>
+
+<h3 id="commit_changes">Commit your changes</h3>
+
+<p>
 Once you have edited files, you must tell Git that they have been modified.
 You must also tell Git about any files that are added, removed, or renamed files.
 These operations are done with the usual Git commands,
@@ -311,16 +395,19 @@
 </p>
 
 <p>
-If you wish to checkpoint your work, or are ready to send the code out for review, run</p>
+Once you have the changes queued up, you will want to commit them.
+In the Go contribution workflow this is done with a `git change` command,
+which creates a local branch and commits the changes directly to that local branch.
+</p>
 
 <pre>
 $ git change <i>&lt;branch&gt;</i>
 </pre>
 
 <p>
-from any directory in your Go repository to commit the changes so far.
 The name <i>&lt;branch&gt;</i> is an arbitrary one you choose to identify the
-local branch containing your changes.
+local branch containing your changes and will not be used elsewhere.
+This is an offline operation and nothing will be sent to the server yet.
 </p>
 
 <p>
@@ -331,9 +418,11 @@
 </p>
 
 <p>
-Git will open a change description file in your editor.
+As the `git commit` is the final step, Git will open an editor to ask for a
+commit message.
 (It uses the editor named by the <code>$EDITOR</code> environment variable,
 <code>vi</code> by default.)
+
 The file will look like:
 </p>
 
@@ -352,7 +441,7 @@
 with a thorough description of your change.
 The first line of the change description is conventionally a one-line
 summary of the change, prefixed by the primary affected package,
-and is used as the subject for code review mail.
+and is used as the subject for code review email.
 It should complete the sentence "This change modifies Go to _____."
 The rest of the description elaborates and should provide context for the
 change and explain what it does.
@@ -395,7 +484,7 @@
 <p>
 The special notation "Fixes #159" associates the change with issue 159 in the
 <a href="https://golang.org/issue/159">Go issue tracker</a>.
-When this change is eventually submitted, the issue
+When this change is eventually applied, the issue
 tracker will automatically mark the issue as fixed.
 (There are several such conventions, described in detail in the
 <a href="https://help.github.com/articles/closing-issues-via-commit-messages/">GitHub Issue Tracker documentation</a>.)
@@ -407,6 +496,13 @@
 </p>
 
 <p>
+You must have the $EDITOR environment variable set properly and working properly (exiting cleanly)
+for this operation to succeed.
+If you run into any issues at this step, it's likely your editor isn't exiting cleanly.
+Try setting a different editor in your $EDITOR environment variable.
+</p>
+
+<p>
 If you wish to do more editing, re-stage your changes using
 <code>git</code> <code>add</code>, and then run
 </p>
@@ -416,8 +512,8 @@
 </pre>
 
 <p>
-to update the change description and incorporate the staged changes.  The
-change description contains a <code>Change-Id</code> line near the bottom,
+to update the change description and incorporate the staged changes.
+The change description contains a <code>Change-Id</code> line near the bottom,
 added by a Git commit hook during the initial
 <code>git</code> <code>change</code>.
 That line is used by Gerrit to match successive uploads of the same change.
@@ -429,10 +525,38 @@
 runs <code>git</code> <code>commit</code> <code>--amend</code>.)
 </p>
 
-<h3 id="mail">Mail the change for review</h3>
+<h3 id="Testing">Testing</h3>
 
 <p>
-Once the change is ready, mail it out for review:
+You've <a href="code.html">written and tested your code</a>, but
+before sending code out for review, run all the tests for the whole
+tree to make sure the changes don't break other packages or programs:
+</p>
+
+<pre>
+$ cd go/src
+$ ./all.bash
+</pre>
+
+<p>
+(To build under Windows use <code>all.bat</code>.)
+</p>
+
+<p>
+After running for a while, the command should print
+</p>
+
+<pre>
+"ALL TESTS PASSED".
+</pre>
+
+<h3 id="mail">Send the change for review</h3>
+
+<p>
+Once the change is ready, send it for review.
+This is similar to a <code>git push</code> in a GitHub style workflow.
+This is done via the mail alias setup earlier which despite its name, doesn't
+directly mail anything, it simply sends the change to Gerrit via git push.
 </p>
 
 <pre>
@@ -440,25 +564,6 @@
 </pre>
 
 <p>
-You can specify a reviewer or CC interested parties
-using the <code>-r</code> or <code>-cc</code> options.
-Both accept a comma-separated list of email addresses:
-</p>
-
-<pre>
-$ git mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com
-</pre>
-
-<p>
-Unless explicitly told otherwise, such as in the discussion leading
-up to sending in the change list, it's better not to specify a reviewer.
-All changes are automatically CC'ed to the
-<a href="https://groups.google.com/group/golang-codereviews">golang-codereviews@googlegroups.com</a>
-mailing list. If this is your first ever change, there may be a moderation
-delay before it appears on the mailing list, to prevent spam.
-</p>
-
-<p>
 (In Git terms, <code>git</code> <code>mail</code> pushes the local committed
 changes to Gerrit using <code>git</code> <code>push</code> <code>origin</code>
 <code>HEAD:refs/for/master</code>.)
@@ -479,7 +584,76 @@
 remote:   https://go-review.googlesource.com/99999 math: improved Sin, Cos and Tan precision for very large arguments
 </pre>
 
-<h3 id="review">Reviewing code</h3>
+<h3>Troubleshooting</h3>
+
+<p>
+The most common way that the <code>git mail</code> command fails is because the
+email address used has not gone through the setup above.
+<br>
+If you see something like...
+</p>
+
+<pre>
+remote: Processing changes: refs: 1, done
+remote:
+remote: ERROR:  In commit ab13517fa29487dcf8b0d48916c51639426c5ee9
+remote: ERROR:  author email address XXXXXXXXXXXXXXXXXXX
+remote: ERROR:  does not match your user account.
+</pre>
+
+<p>
+You need to either add the email address listed to the CLA or set this repo to use
+another email address already approved.
+</p>
+
+<p>
+First let's change the email address for this repo so this doesn't happen again.
+You can change your email address for this repo with the following command:
+</p>
+
+<pre>
+$ git config user.email email@address.com
+</pre>
+
+<p>
+Then change the previous commit to use this alternative email address.
+You can do that with:
+</p>
+
+<pre>
+$ git commit --amend --author="Author Name &lt;email@address.com&gt;"
+</pre>
+
+<p>
+Finally try to resend with:
+</p>
+
+<pre>
+$ git mail
+</pre>
+
+<h3 id="cc">Specifying a reviewer / CCing others</h3>
+
+<p>
+Unless explicitly told otherwise, such as in the discussion leading
+up to sending in the change list, it's better not to specify a reviewer.
+All changes are automatically CC'ed to the
+<a href="https://groups.google.com/group/golang-codereviews">golang-codereviews@googlegroups.com</a>
+mailing list. If this is your first ever change, there may be a moderation
+delay before it appears on the mailing list, to prevent spam.
+</p>
+
+<p>
+You can specify a reviewer or CC interested parties
+using the <code>-r</code> or <code>-cc</code> options.
+Both accept a comma-separated list of email addresses:
+</p>
+
+<pre>
+$ git mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com
+</pre>
+
+<h2 id="review">Going through the review process</h2>
 
 <p>
 Running <code>git</code> <code>mail</code> will send an email to you and the
@@ -491,7 +665,15 @@
 (Unlike with the old Rietveld review system, replying by mail has no effect.)
 </p>
 
-<h3 id="revise">Revise and upload</h3>
+<h3 id="revise">Revise and resend</h3>
+
+<p>
+The Go contribution workflow is optimized for iterative revisions based on
+feedback.
+It is rare that an initial contribution will be ready to be applied as is.
+As you revise your contribution and resend Gerrit will retain a history of
+all the changes and comments made in the single URL.
+</p>
 
 <p>
 You must respond to review comments through the web interface.
@@ -534,6 +716,8 @@
 <code>git</code> <code>pull</code> <code>-r</code>.)
 </p>
 
+<h3 id="resolving_conflicts">Resolving Conflicts</h3>
+
 <p>
 If files you were editing have changed, Git does its best to merge the
 remote changes into your local changes.
@@ -609,8 +793,8 @@
 <p>
 Git doesn't show it, but suppose the original text that both edits
 started with was 1e8; you changed it to 1e10 and the other change to 1e9,
-so the correct answer might now be 1e10.  First, edit the section
-to remove the markers and leave the correct code:
+so the correct answer might now be 1e10.
+First, edit the section to remove the markers and leave the correct code:
 </p>
 
 <pre>
@@ -639,10 +823,13 @@
 <h3 id="download">Reviewing code by others</h3>
 
 <p>
-You can import a change proposed by someone else into your local Git repository.
+As part of the review process reviewers can propose changes directly (in the
+GitHub workflow this would be someone else attaching commits to a pull request).
+
+You can import these changes proposed by someone else into your local Git repository.
 On the Gerrit review page, click the "Download â–¼" link in the upper right
-corner, copy the "Checkout" command and run it from your local Git repo.
-It should look something like this:
+corner, copy the "Checkout" command and run it from your local Git repo. It
+should look something like this:
 </p>
 
 <pre>
@@ -653,11 +840,11 @@
 To revert, change back to the branch you were working in.
 </p>
 
-<h3 id="submit">Submit the change after the review</h3>
+<h2 id="submit">Apply the change to the master branch</h2>
 
 <p>
 After the code has been <code>LGTM</code>'ed, an approver may
-submit it to the master branch using the Gerrit UI.
+apply it to the master branch using the Gerrit UI.
 There is a "Submit" button on the web page for the change
 that appears once the change is approved (marked +2).
 </p>
@@ -669,41 +856,13 @@
 in the repository.
 Since the method used to integrate the changes is "Cherry Pick",
 the commit hashes in the repository will be changed by
-the submit operation.
+the "Submit" operation.
 </p>
 
-<h3 id="more">More information</h3>
+<h2 id="more">More information</h2>
 
 <p>
-In addition to the information here, the Go community maintains a <a href="https://golang.org/wiki/CodeReview">CodeReview</a> wiki page.
+In addition to the information here, the Go community maintains a <a
+href="https://golang.org/wiki/CodeReview">CodeReview</a> wiki page.
 Feel free to contribute to this page as you learn the review process.
 </p>
-
-<h2 id="copyright">Copyright</h2>
-
-<p>Files in the Go repository don't list author names,
-both to avoid clutter and to avoid having to keep the lists up to date.
-Instead, your name will appear in the
-<a href="https://golang.org/change">change log</a>
-and in the <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file
-and perhaps the <a href="/AUTHORS"><code>AUTHORS</code></a> file.
-</p>
-
-<p>The <a href="/CONTRIBUTORS"><code>CONTRIBUTORS</code></a> file
-defines who the Go contributors&mdash;the people&mdash;are;
-the <a href="/AUTHORS"><code>AUTHORS</code></a> file defines
-who &ldquo;The Go Authors&rdquo;&mdash;the copyright holders&mdash;are.
-These files will be periodically updated based on the commit logs.
-
-<p>Code that you contribute should use the standard copyright header:</p>
-
-<pre>
-// Copyright 2017 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.
-</pre>
-
-<p>
-Files in the repository are copyright the year they are added. It is not
-necessary to update the copyright year on files that you change.
-</p>
diff --git a/doc/devel/release.html b/doc/devel/release.html
index be340a3..c4ca6a6 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -30,6 +30,25 @@
 See the <a href="/security">security policy</a> for more details.
 </p>
 
+<h2 id="go1.8">go1.8 (released 2017/02/16)</h2>
+
+<p>
+Go 1.8 is a major release of Go.
+Read the <a href="/doc/go1.8">Go 1.8 Release Notes</a> for more information.
+</p>
+
+<h3 id="go1.8.minor">Minor revisions</h3>
+
+<p>
+go1.8.1 (released 2017/04/07) includes fixes to the compiler, linker, runtime,
+documentation, <code>go</code> command and the <code>crypto/tls</code>,
+<code>encoding/xml</code>, <code>image/png</code>, <code>net</code>,
+<code>net/http</code>, <code>reflect</code>, <code>text/template</code>,
+and <code>time</code> packages.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.1">Go
+1.8.1 milestone</a> on our issue tracker for details.
+</p>
+
 <h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
 
 <p>
diff --git a/doc/go1.8.html b/doc/go1.8.html
index 9e3145e..611f5ee 100644
--- a/doc/go1.8.html
+++ b/doc/go1.8.html
@@ -15,12 +15,7 @@
 ul li { margin: 0.5em 0; }
 </style>
 
-<h2 id="introduction">DRAFT RELEASE NOTES - Introduction to Go 1.8</h2>
-
-<p><strong>
-Go 1.8 is not yet released. These are work-in-progress
-release notes. Go 1.8 is expected to be released in February 2017.
-</strong></p>
+<h2 id="introduction">Introduction to Go 1.8</h2>
 
 <p>
 The latest Go release, version 1.8, arrives six months after <a href="go1.7">Go 1.7</a>.
@@ -1309,7 +1304,7 @@
         request must have the new
         <a href="/pkg/net/http/#Request"><code>Request.GetBody</code></a>
         field defined.
-        <a href="pkg/net/http/#NewRequest"><code>NewRequest</code></a>
+        <a href="/pkg/net/http/#NewRequest"><code>NewRequest</code></a>
         sets <code>Request.GetBody</code> automatically for common
         body types.
       </li>
diff --git a/doc/install-source.html b/doc/install-source.html
index efe864c..8fb26a9 100644
--- a/doc/install-source.html
+++ b/doc/install-source.html
@@ -221,7 +221,7 @@
 Change to the directory that will be its parent
 and make sure the <code>go</code> directory does not exist.
 Then clone the repository and check out the latest release tag
-(<code class="versionTag">go1.7.4</code>, for example):</p>
+(<code class="versionTag">go1.8.1</code>, for example):</p>
 
 <pre>
 $ git clone https://go.googlesource.com/go
@@ -409,7 +409,7 @@
 <a href="//groups.google.com/group/golang-announce">golang-announce</a>
 mailing list.
 Each announcement mentions the latest release tag, for instance,
-<code class="versionTag">go1.7.4</code>.
+<code class="versionTag">go1.8.1</code>.
 </p>
 
 <p>
diff --git a/misc/cgo/testcshared/test.bash b/misc/cgo/testcshared/test.bash
index 052ee0e..0315fb0 100755
--- a/misc/cgo/testcshared/test.bash
+++ b/misc/cgo/testcshared/test.bash
@@ -179,6 +179,13 @@
     status=1
 fi
 
+if test "$libext" = "dylib"; then
+	# make sure dylibs are well-formed
+	if ! otool -l libgo*.dylib >/dev/null; then
+		status=1
+	fi
+fi
+
 if test $status = 0; then
     echo "ok"
 fi
diff --git a/src/cmd/compile/internal/gc/esc.go b/src/cmd/compile/internal/gc/esc.go
index 4f37ff0..f4a70c4 100644
--- a/src/cmd/compile/internal/gc/esc.go
+++ b/src/cmd/compile/internal/gc/esc.go
@@ -477,6 +477,10 @@
 	for _, n := range all {
 		if n.Op == ODCLFUNC {
 			n.Esc = EscFuncPlanned
+			if Debug['m'] > 3 {
+				Dump("escAnalyze", n)
+			}
+
 		}
 	}
 
@@ -1675,7 +1679,10 @@
 	}
 
 	// Don't bother building a graph for scalars.
-	if src.Type != nil && !haspointers(src.Type) {
+	if src.Type != nil && !haspointers(src.Type) && !isReflectHeaderDataField(src) {
+		if Debug['m'] > 3 {
+			fmt.Printf("%v::NOT flows:: %S <- %S\n", linestr(lineno), dst, src)
+		}
 		return
 	}
 
diff --git a/src/cmd/compile/internal/gc/sinit.go b/src/cmd/compile/internal/gc/sinit.go
index 6b3c426..416e2b2 100644
--- a/src/cmd/compile/internal/gc/sinit.go
+++ b/src/cmd/compile/internal/gc/sinit.go
@@ -585,7 +585,7 @@
 }
 
 func (n *Node) isSimpleName() bool {
-	return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP
+	return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP && n.Class != PEXTERN
 }
 
 func litas(l *Node, r *Node, init *Nodes) {
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index bf483f8..a0c1cf1 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -3470,8 +3470,13 @@
 	if s.WBLineno == 0 {
 		s.WBLineno = left.Line
 	}
-	s.storeTypeScalars(t, left, right, skip)
-	s.storeTypePtrsWB(t, left, right)
+	if t == Types[TUINTPTR] {
+		// Stores to reflect.{Slice,String}Header.Data.
+		s.vars[&memVar] = s.newValue3I(ssa.OpStoreWB, ssa.TypeMem, s.config.PtrSize, left, right, s.mem())
+	} else {
+		s.storeTypeScalars(t, left, right, skip)
+		s.storeTypePtrsWB(t, left, right)
+	}
 
 	// WB ops will be expanded to branches at writebarrier phase.
 	// To make it easy, we put WB ops at the end of a block, so
diff --git a/src/cmd/compile/internal/gc/testdata/arith.go b/src/cmd/compile/internal/gc/testdata/arith.go
index d850ce2..f260d45 100644
--- a/src/cmd/compile/internal/gc/testdata/arith.go
+++ b/src/cmd/compile/internal/gc/testdata/arith.go
@@ -488,6 +488,17 @@
 			wantA, wantB, wantC, wantD, ", got", a, b, c, d)
 		failed = true
 	}
+	// Also test inputs with the top bit set, and make sure
+	// sub-word right shift has high bits cleared first.
+	// See issue #19270.
+	wantA, wantB, wantC, wantD = uint8(0xdf), uint16(0xdfff),
+		uint32(0xdfffffff), uint64(0xdfffffffffffffff)
+	a, b, c, d = lrot1_ssa(0xfe, 0xfffe, 0xfffffffe, 0xfffffffffffffffe)
+	if a != wantA || b != wantB || c != wantC || d != wantD {
+		println("lrot1_ssa(0xfe, 0xfffe, 0xfffffffe, 0xfffffffffffffffe)=",
+			wantA, wantB, wantC, wantD, ", got", a, b, c, d)
+		failed = true
+	}
 	x := lrot2_ssa(0xb0000001, 32)
 	wantX := uint32(0xb0000001)
 	if x != wantX {
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 1379bb5..d5aa0a8 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -1114,7 +1114,7 @@
 
 	case OSLICE, OSLICE3:
 		ok |= Erv
-		n.Left = typecheck(n.Left, top)
+		n.Left = typecheck(n.Left, Erv)
 		low, high, max := n.SliceBounds()
 		hasmax := n.Op.IsSlice3()
 		low = typecheck(low, Erv)
@@ -1126,6 +1126,10 @@
 		max = indexlit(max)
 		n.SetSliceBounds(low, high, max)
 		l := n.Left
+		if l.Type == nil {
+			n.Type = nil
+			return n
+		}
 		if l.Type.IsArray() {
 			if !islvalue(n.Left) {
 				yyerror("invalid operation %v (slice of unaddressable value)", n)
@@ -1138,12 +1142,7 @@
 			n.Left = typecheck(n.Left, Erv)
 			l = n.Left
 		}
-
 		t := l.Type
-		if t == nil {
-			n.Type = nil
-			return n
-		}
 		var tp *Type
 		if t.IsString() {
 			if hasmax {
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 7c2e2ab..d080d21 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -2071,6 +2071,29 @@
 	return false
 }
 
+// isReflectHeaderDataField reports whether l is an expression p.Data
+// where p has type reflect.SliceHeader or reflect.StringHeader.
+func isReflectHeaderDataField(l *Node) bool {
+	if l.Type != Types[TUINTPTR] {
+		return false
+	}
+
+	var tsym *Sym
+	switch l.Op {
+	case ODOT:
+		tsym = l.Left.Type.Sym
+	case ODOTPTR:
+		tsym = l.Left.Type.Elem().Sym
+	default:
+		return false
+	}
+
+	if tsym == nil || l.Sym.Name != "Data" || tsym.Pkg.Path != "reflect" {
+		return false
+	}
+	return tsym.Name == "SliceHeader" || tsym.Name == "StringHeader"
+}
+
 // Do we need a write barrier for the assignment l = r?
 func needwritebarrier(l *Node, r *Node) bool {
 	if !use_writebarrier {
@@ -2081,15 +2104,21 @@
 		return false
 	}
 
-	// No write barrier for write of non-pointers.
-	dowidth(l.Type)
-
-	if !haspointers(l.Type) {
+	// No write barrier for write to stack.
+	if isstack(l) {
 		return false
 	}
 
-	// No write barrier for write to stack.
-	if isstack(l) {
+	// Package unsafe's documentation says storing pointers into
+	// reflect.SliceHeader and reflect.StringHeader's Data fields
+	// is valid, even though they have type uintptr (#19168).
+	if isReflectHeaderDataField(l) {
+		return true
+	}
+
+	// No write barrier for write of non-pointers.
+	dowidth(l.Type)
+	if !haspointers(l.Type) {
 		return false
 	}
 
diff --git a/src/cmd/compile/internal/ssa/deadcode.go b/src/cmd/compile/internal/ssa/deadcode.go
index d75d2d5..ce786a9 100644
--- a/src/cmd/compile/internal/ssa/deadcode.go
+++ b/src/cmd/compile/internal/ssa/deadcode.go
@@ -64,7 +64,7 @@
 			q = append(q, v)
 		}
 		for _, v := range b.Values {
-			if opcodeTable[v.Op].call && !live[v.ID] {
+			if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects) && !live[v.ID] {
 				live[v.ID] = true
 				q = append(q, v)
 			}
diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go
index 3a9357d..ee6ed51 100644
--- a/src/cmd/compile/internal/ssa/export_test.go
+++ b/src/cmd/compile/internal/ssa/export_test.go
@@ -6,6 +6,7 @@
 
 import (
 	"cmd/internal/obj"
+	"cmd/internal/obj/s390x"
 	"cmd/internal/obj/x86"
 	"testing"
 )
@@ -21,6 +22,10 @@
 	return NewConfig("amd64", DummyFrontend{t}, testCtxt, true)
 }
 
+func testConfigS390X(t testing.TB) *Config {
+	return NewConfig("s390x", DummyFrontend{t}, obj.Linknew(&s390x.Links390x), true)
+}
+
 // DummyFrontend is a test-only frontend.
 // It assumes 64 bit integers and pointers.
 type DummyFrontend struct {
diff --git a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
index 5a293d1..016ed4f 100644
--- a/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
@@ -522,15 +522,15 @@
 		// store arg0 to arg1+auxint+aux, arg2=mem.
 		// These ops return a tuple of <old contents of *(arg1+auxint+aux), memory>.
 		// Note: arg0 and arg1 are backwards compared to MOVLstore (to facilitate resultInArg0)!
-		{name: "XCHGL", argLength: 3, reg: gpstorexchg, asm: "XCHGL", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true},
-		{name: "XCHGQ", argLength: 3, reg: gpstorexchg, asm: "XCHGQ", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true},
+		{name: "XCHGL", argLength: 3, reg: gpstorexchg, asm: "XCHGL", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true},
+		{name: "XCHGQ", argLength: 3, reg: gpstorexchg, asm: "XCHGQ", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true},
 
 		// Atomic adds.
 		// *(arg1+auxint+aux) += arg0.  arg2=mem.
 		// Returns a tuple of <old contents of *(arg1+auxint+aux), memory>.
 		// Note: arg0 and arg1 are backwards compared to MOVLstore (to facilitate resultInArg0)!
-		{name: "XADDLlock", argLength: 3, reg: gpstorexchg, asm: "XADDL", typ: "(UInt32,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true},
-		{name: "XADDQlock", argLength: 3, reg: gpstorexchg, asm: "XADDQ", typ: "(UInt64,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true},
+		{name: "XADDLlock", argLength: 3, reg: gpstorexchg, asm: "XADDL", typ: "(UInt32,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, hasSideEffects: true},
+		{name: "XADDQlock", argLength: 3, reg: gpstorexchg, asm: "XADDQ", typ: "(UInt64,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, hasSideEffects: true},
 		{name: "AddTupleFirst32", argLength: 2}, // arg0=tuple <x,y>.  Returns <x+arg1,y>.
 		{name: "AddTupleFirst64", argLength: 2}, // arg0=tuple <x,y>.  Returns <x+arg1,y>.
 
@@ -553,12 +553,12 @@
 		//    JEQ ...
 		// but we can't do that because memory-using ops can't generate flags yet
 		// (flagalloc wants to move flag-generating instructions around).
-		{name: "CMPXCHGLlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
-		{name: "CMPXCHGQlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGQ", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
+		{name: "CMPXCHGLlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGL", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "CMPXCHGQlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGQ", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// Atomic memory updates.
-		{name: "ANDBlock", argLength: 3, reg: gpstore, asm: "ANDB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true}, // *(arg0+auxint+aux) &= arg1
-		{name: "ORBlock", argLength: 3, reg: gpstore, asm: "ORB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},   // *(arg0+auxint+aux) |= arg1
+		{name: "ANDBlock", argLength: 3, reg: gpstore, asm: "ANDB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true}, // *(arg0+auxint+aux) &= arg1
+		{name: "ORBlock", argLength: 3, reg: gpstore, asm: "ORB", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},   // *(arg0+auxint+aux) |= arg1
 	}
 
 	var AMD64blocks = []blockData{
diff --git a/src/cmd/compile/internal/ssa/gen/ARM.rules b/src/cmd/compile/internal/ssa/gen/ARM.rules
index bea9d6c..aad2587 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM.rules
@@ -178,8 +178,8 @@
 (Rsh8x64 x (Const64 [c])) && uint64(c) >= 8 -> (SRAconst (SLLconst <config.fe.TypeUInt32()> x [24]) [31])
 
 (Lrot32 x [c]) -> (SRRconst x [32-c&31])
-(Lrot16 <t> x [c]) -> (OR (SLLconst <t> x [c&15]) (SRLconst <t> x [16-c&15]))
-(Lrot8 <t> x [c]) -> (OR (SLLconst <t> x [c&7]) (SRLconst <t> x [8-c&7]))
+(Lrot16 <t> x [c]) -> (OR (SLLconst <t> x [c&15]) (SRLconst <t> (ZeroExt16to32 x) [16-c&15]))
+(Lrot8 <t> x [c]) -> (OR (SLLconst <t> x [c&7]) (SRLconst <t> (ZeroExt8to32 x) [8-c&7]))
 
 // constants
 (Const8 [val]) -> (MOVWconst [val])
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64.rules b/src/cmd/compile/internal/ssa/gen/ARM64.rules
index c36b6f7..bc58a1f 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64.rules
+++ b/src/cmd/compile/internal/ssa/gen/ARM64.rules
@@ -529,110 +529,148 @@
 // can be encoded in the instructions
 // since this rewriting takes place before stack allocation, the offset to SP is unknown,
 // so don't do it for args and locals with unaligned offset
-(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBload [off1+off2] {sym} ptr mem)
-(MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBUload [off1+off2] {sym} ptr mem)
+(MOVBload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2) ->
+	(MOVBload [off1+off2] {sym} ptr mem)
+(MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2) ->
+	(MOVBUload [off1+off2] {sym} ptr mem)
 (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVHload [off1+off2] {sym} ptr mem)
 (MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVHUload [off1+off2] {sym} ptr mem)
 (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVWload [off1+off2] {sym} ptr mem)
 (MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVWUload [off1+off2] {sym} ptr mem)
 (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVDload [off1+off2] {sym} ptr mem)
 (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(FMOVSload [off1+off2] {sym} ptr mem)
 (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(FMOVDload [off1+off2] {sym} ptr mem)
 
-(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVBstore [off1+off2] {sym} ptr val mem)
+(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2) ->
+	(MOVBstore [off1+off2] {sym} ptr val mem)
 (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVHstore [off1+off2] {sym} ptr val mem)
 (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVWstore [off1+off2] {sym} ptr val mem)
 (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVDstore [off1+off2] {sym} ptr val mem)
 (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(FMOVSstore [off1+off2] {sym} ptr val mem)
 (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(FMOVDstore [off1+off2] {sym} ptr val mem)
-(MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBstorezero [off1+off2] {sym} ptr mem)
+(MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2) ->
+	(MOVBstorezero [off1+off2] {sym} ptr mem)
 (MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVHstorezero [off1+off2] {sym} ptr mem)
 (MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVWstorezero [off1+off2] {sym} ptr mem)
 (MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
-	&& (off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
+	&& is32Bit(off1+off2) && !isArg(sym)
+	&& ((off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
 	(MOVDstorezero [off1+off2] {sym} ptr mem)
 
-(MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
+(MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+	&& is32Bit(off1+off2) ->
 	(MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
-(MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
+(MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+	&& is32Bit(off1+off2) ->
 	(MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 
-(MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
+(MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
+	&& is32Bit(off1+off2) ->
 	(MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 (MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 (MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 (MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
-(MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
+(MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
+	&& is32Bit(off1+off2) ->
 	(MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 (MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
-	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
+	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
+	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
 	(MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 
 // store zero
diff --git a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
index e8d5be2..0986ac6 100644
--- a/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
+++ b/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
@@ -456,16 +456,16 @@
 
 		// atomic stores.
 		// store arg1 to arg0. arg2=mem. returns memory. auxint must be zero.
-		{name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true},
-		{name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true},
+		{name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true, hasSideEffects: true},
+		{name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true, hasSideEffects: true},
 
 		// atomic exchange.
 		// store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>. auxint must be zero.
 		// LDAXR	(Rarg0), Rout
 		// STLXR	Rarg1, (Rarg0), Rtmp
 		// CBNZ		Rtmp, -2(PC)
-		{name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
-		{name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
+		{name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// atomic add.
 		// *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
@@ -473,8 +473,8 @@
 		// ADD		Rarg1, Rout
 		// STLXR	Rout, (Rarg0), Rtmp
 		// CBNZ		Rtmp, -3(PC)
-		{name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
-		{name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
+		{name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// atomic compare and swap.
 		// arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory. auxint must be zero.
@@ -490,8 +490,8 @@
 		// STLXR	Rarg2, (Rarg0), Rtmp
 		// CBNZ		Rtmp, -4(PC)
 		// CSET		EQ, Rout
-		{name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true},
-		{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true},
+		{name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// atomic and/or.
 		// *arg0 &= (|=) arg1. arg2=mem. returns memory. auxint must be zero.
@@ -499,8 +499,8 @@
 		// AND/OR	Rarg1, Rtmp
 		// STLXRB	Rtmp, (Rarg0), Rtmp
 		// CBNZ		Rtmp, -3(PC)
-		{name: "LoweredAtomicAnd8", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true},
-		{name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "ORR", faultOnNilArg0: true},
+		{name: "LoweredAtomicAnd8", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "ORR", faultOnNilArg0: true, hasSideEffects: true},
 	}
 
 	blocks := []blockData{
diff --git a/src/cmd/compile/internal/ssa/gen/ARMOps.go b/src/cmd/compile/internal/ssa/gen/ARMOps.go
index e296d06..6d9a90a 100644
--- a/src/cmd/compile/internal/ssa/gen/ARMOps.go
+++ b/src/cmd/compile/internal/ssa/gen/ARMOps.go
@@ -119,8 +119,8 @@
 		fp01      = regInfo{inputs: nil, outputs: []regMask{fp}}
 		fp11      = regInfo{inputs: []regMask{fp}, outputs: []regMask{fp}}
 		fp1flags  = regInfo{inputs: []regMask{fp}}
-		fpgp      = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
-		gpfp      = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}
+		fpgp      = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}, clobbers: buildReg("F15")} // int-float conversion uses F15 as tmp
+		gpfp      = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}, clobbers: buildReg("F15")}
 		fp21      = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
 		fp2flags  = regInfo{inputs: []regMask{fp, fp}}
 		fpload    = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}
diff --git a/src/cmd/compile/internal/ssa/gen/MIPS.rules b/src/cmd/compile/internal/ssa/gen/MIPS.rules
index 008f1b1..ad7a954 100644
--- a/src/cmd/compile/internal/ssa/gen/MIPS.rules
+++ b/src/cmd/compile/internal/ssa/gen/MIPS.rules
@@ -404,8 +404,7 @@
 				(ANDconst  <config.fe.TypeUInt32()> [3] ptr)))
 		(NORconst [0] <config.fe.TypeUInt32()> (SLL <config.fe.TypeUInt32()>
 			(MOVWconst [0xff]) (SLLconst <config.fe.TypeUInt32()> [3]
-				(ANDconst <config.fe.TypeUInt32()> [3]
-					(XORconst <config.fe.TypeUInt32()> [3] ptr)))))) mem)
+				(ANDconst <config.fe.TypeUInt32()> [3] ptr))))) mem)
 
 // AtomicOr8(ptr,val) -> LoweredAtomicOr(ptr&^3,uint32(val) << (((ptr^3) & 3) * 8))
 (AtomicOr8 ptr val mem) && config.BigEndian ->
diff --git a/src/cmd/compile/internal/ssa/gen/MIPSOps.go b/src/cmd/compile/internal/ssa/gen/MIPSOps.go
index 78b961f..3d88b71 100644
--- a/src/cmd/compile/internal/ssa/gen/MIPSOps.go
+++ b/src/cmd/compile/internal/ssa/gen/MIPSOps.go
@@ -267,8 +267,8 @@
 		// SYNC
 		// MOVW	Rarg1, (Rarg0)
 		// SYNC
-		{name: "LoweredAtomicStore", argLength: 3, reg: gpstore, faultOnNilArg0: true},
-		{name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true},
+		{name: "LoweredAtomicStore", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},
 
 		// atomic exchange.
 		// store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>.
@@ -278,7 +278,7 @@
 		// SC	Rtmp, (Rarg0)
 		// BEQ	Rtmp, -3(PC)
 		// SYNC
-		{name: "LoweredAtomicExchange", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
+		{name: "LoweredAtomicExchange", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// atomic add.
 		// *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>.
@@ -289,8 +289,8 @@
 		// BEQ	Rtmp, -3(PC)
 		// SYNC
 		// ADDU Rarg1, Rout
-		{name: "LoweredAtomicAdd", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
-		{name: "LoweredAtomicAddconst", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int32", resultNotInArgs: true, faultOnNilArg0: true},
+		{name: "LoweredAtomicAdd", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicAddconst", argLength: 2, reg: regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{gp}}, aux: "Int32", resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// atomic compare and swap.
 		// arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory.
@@ -308,7 +308,7 @@
 		// SC	Rout, (Rarg0)
 		// BEQ	Rout, -4(PC)
 		// SYNC
-		{name: "LoweredAtomicCas", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true},
+		{name: "LoweredAtomicCas", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// atomic and/or.
 		// *arg0 &= (|=) arg1. arg2=mem. returns memory.
@@ -318,8 +318,8 @@
 		// SC	Rtmp, (Rarg0)
 		// BEQ	Rtmp, -3(PC)
 		// SYNC
-		{name: "LoweredAtomicAnd", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true},
-		{name: "LoweredAtomicOr", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true},
+		{name: "LoweredAtomicAnd", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicOr", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true, hasSideEffects: true},
 
 		// large or unaligned zeroing
 		// arg0 = address of memory to zero (in R1, changed as side effect)
diff --git a/src/cmd/compile/internal/ssa/gen/S390X.rules b/src/cmd/compile/internal/ssa/gen/S390X.rules
index c26515c..7ecea02 100644
--- a/src/cmd/compile/internal/ssa/gen/S390X.rules
+++ b/src/cmd/compile/internal/ssa/gen/S390X.rules
@@ -440,7 +440,7 @@
 (If (MOVDGTnoinv (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (GTF cmp yes no)
 (If (MOVDGEnoinv (MOVDconst [0]) (MOVDconst [1]) cmp) yes no) -> (GEF cmp yes no)
 
-(If cond yes no) -> (NE (CMPWconst [0] (MOVBZreg cond)) yes no)
+(If cond yes no) -> (NE (CMPWconst [0] (MOVBZreg <config.fe.TypeBool()> cond)) yes no)
 
 // ***************************
 // Above: lowering rules
@@ -448,7 +448,15 @@
 // ***************************
 // TODO: Should the optimizations be a separate pass?
 
-// if a register move has only 1 use, just use the same register without emitting instruction
+// Fold unnecessary type conversions.
+(MOVDreg <t> x) && t.Compare(x.Type) == CMPeq -> x
+(MOVDnop <t> x) && t.Compare(x.Type) == CMPeq -> x
+
+// Propagate constants through type conversions.
+(MOVDreg (MOVDconst [c])) -> (MOVDconst [c])
+(MOVDnop (MOVDconst [c])) -> (MOVDconst [c])
+
+// If a register move has only 1 use, just use the same register without emitting instruction.
 // MOVDnop doesn't emit instruction, only for ensuring the type.
 (MOVDreg x) && x.Uses == 1 -> (MOVDnop x)
 
diff --git a/src/cmd/compile/internal/ssa/gen/S390XOps.go b/src/cmd/compile/internal/ssa/gen/S390XOps.go
index 29383f6..6fdeb2e 100644
--- a/src/cmd/compile/internal/ssa/gen/S390XOps.go
+++ b/src/cmd/compile/internal/ssa/gen/S390XOps.go
@@ -429,14 +429,14 @@
 
 		// Atomic stores. These are just normal stores.
 		// store arg1 to arg0+auxint+aux. arg2=mem.
-		{name: "MOVWatomicstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true},
-		{name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true},
+		{name: "MOVWatomicstore", argLength: 3, reg: gpstore, asm: "MOVW", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// Atomic adds.
 		// *(arg0+auxint+aux) += arg1.  arg2=mem.
 		// Returns a tuple of <old contents of *(arg0+auxint+aux), memory>.
-		{name: "LAA", argLength: 3, reg: gpstorelaa, asm: "LAA", typ: "(UInt32,Mem)", aux: "SymOff", faultOnNilArg0: true},
-		{name: "LAAG", argLength: 3, reg: gpstorelaa, asm: "LAAG", typ: "(UInt64,Mem)", aux: "SymOff", faultOnNilArg0: true},
+		{name: "LAA", argLength: 3, reg: gpstorelaa, asm: "LAA", typ: "(UInt32,Mem)", aux: "SymOff", faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LAAG", argLength: 3, reg: gpstorelaa, asm: "LAAG", typ: "(UInt64,Mem)", aux: "SymOff", faultOnNilArg0: true, hasSideEffects: true},
 		{name: "AddTupleFirst32", argLength: 2}, // arg0=tuple <x,y>.  Returns <x+arg1,y>.
 		{name: "AddTupleFirst64", argLength: 2}, // arg0=tuple <x,y>.  Returns <x+arg1,y>.
 
@@ -461,13 +461,13 @@
 		//    BEQ ...
 		// but we can't do that because memory-using ops can't generate flags yet
 		// (flagalloc wants to move flag-generating instructions around).
-		{name: "LoweredAtomicCas32", argLength: 4, reg: cas, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
-		{name: "LoweredAtomicCas64", argLength: 4, reg: cas, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
+		{name: "LoweredAtomicCas32", argLength: 4, reg: cas, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicCas64", argLength: 4, reg: cas, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// Lowered atomic swaps, emulated using compare-and-swap.
 		// store arg1 to arg0+auxint+aux, arg2=mem.
-		{name: "LoweredAtomicExchange32", argLength: 3, reg: exchange, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
-		{name: "LoweredAtomicExchange64", argLength: 3, reg: exchange, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true},
+		{name: "LoweredAtomicExchange32", argLength: 3, reg: exchange, asm: "CS", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
+		{name: "LoweredAtomicExchange64", argLength: 3, reg: exchange, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
 
 		// find leftmost one
 		{
diff --git a/src/cmd/compile/internal/ssa/gen/genericOps.go b/src/cmd/compile/internal/ssa/gen/genericOps.go
index fe93e52..b1689df 100644
--- a/src/cmd/compile/internal/ssa/gen/genericOps.go
+++ b/src/cmd/compile/internal/ssa/gen/genericOps.go
@@ -460,20 +460,20 @@
 	// Atomic loads return a new memory so that the loads are properly ordered
 	// with respect to other loads and stores.
 	// TODO: use for sync/atomic at some point.
-	{name: "AtomicLoad32", argLength: 2, typ: "(UInt32,Mem)"},         // Load from arg0.  arg1=memory.  Returns loaded value and new memory.
-	{name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"},         // Load from arg0.  arg1=memory.  Returns loaded value and new memory.
-	{name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"},       // Load from arg0.  arg1=memory.  Returns loaded value and new memory.
-	{name: "AtomicStore32", argLength: 3, typ: "Mem"},                 // Store arg1 to *arg0.  arg2=memory.  Returns memory.
-	{name: "AtomicStore64", argLength: 3, typ: "Mem"},                 // Store arg1 to *arg0.  arg2=memory.  Returns memory.
-	{name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem"},            // Store arg1 to *arg0.  arg2=memory.  Returns memory.
-	{name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)"},     // Store arg1 to *arg0.  arg2=memory.  Returns old contents of *arg0 and new memory.
-	{name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)"},     // Store arg1 to *arg0.  arg2=memory.  Returns old contents of *arg0 and new memory.
-	{name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)"},          // Do *arg0 += arg1.  arg2=memory.  Returns sum and new memory.
-	{name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)"},          // Do *arg0 += arg1.  arg2=memory.  Returns sum and new memory.
-	{name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)"}, // if *arg0==arg1, then set *arg0=arg2.  Returns true iff store happens and new memory.
-	{name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)"}, // if *arg0==arg1, then set *arg0=arg2.  Returns true iff store happens and new memory.
-	{name: "AtomicAnd8", argLength: 3, typ: "Mem"},                    // *arg0 &= arg1.  arg2=memory.  Returns memory.
-	{name: "AtomicOr8", argLength: 3, typ: "Mem"},                     // *arg0 |= arg1.  arg2=memory.  Returns memory.
+	{name: "AtomicLoad32", argLength: 2, typ: "(UInt32,Mem)"},                               // Load from arg0.  arg1=memory.  Returns loaded value and new memory.
+	{name: "AtomicLoad64", argLength: 2, typ: "(UInt64,Mem)"},                               // Load from arg0.  arg1=memory.  Returns loaded value and new memory.
+	{name: "AtomicLoadPtr", argLength: 2, typ: "(BytePtr,Mem)"},                             // Load from arg0.  arg1=memory.  Returns loaded value and new memory.
+	{name: "AtomicStore32", argLength: 3, typ: "Mem", hasSideEffects: true},                 // Store arg1 to *arg0.  arg2=memory.  Returns memory.
+	{name: "AtomicStore64", argLength: 3, typ: "Mem", hasSideEffects: true},                 // Store arg1 to *arg0.  arg2=memory.  Returns memory.
+	{name: "AtomicStorePtrNoWB", argLength: 3, typ: "Mem", hasSideEffects: true},            // Store arg1 to *arg0.  arg2=memory.  Returns memory.
+	{name: "AtomicExchange32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true},     // Store arg1 to *arg0.  arg2=memory.  Returns old contents of *arg0 and new memory.
+	{name: "AtomicExchange64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true},     // Store arg1 to *arg0.  arg2=memory.  Returns old contents of *arg0 and new memory.
+	{name: "AtomicAdd32", argLength: 3, typ: "(UInt32,Mem)", hasSideEffects: true},          // Do *arg0 += arg1.  arg2=memory.  Returns sum and new memory.
+	{name: "AtomicAdd64", argLength: 3, typ: "(UInt64,Mem)", hasSideEffects: true},          // Do *arg0 += arg1.  arg2=memory.  Returns sum and new memory.
+	{name: "AtomicCompareAndSwap32", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2.  Returns true iff store happens and new memory.
+	{name: "AtomicCompareAndSwap64", argLength: 4, typ: "(Bool,Mem)", hasSideEffects: true}, // if *arg0==arg1, then set *arg0=arg2.  Returns true iff store happens and new memory.
+	{name: "AtomicAnd8", argLength: 3, typ: "Mem", hasSideEffects: true},                    // *arg0 &= arg1.  arg2=memory.  Returns memory.
+	{name: "AtomicOr8", argLength: 3, typ: "Mem", hasSideEffects: true},                     // *arg0 |= arg1.  arg2=memory.  Returns memory.
 }
 
 //     kind           control    successors       implicit exit
diff --git a/src/cmd/compile/internal/ssa/gen/main.go b/src/cmd/compile/internal/ssa/gen/main.go
index 41199f7..19b904a 100644
--- a/src/cmd/compile/internal/ssa/gen/main.go
+++ b/src/cmd/compile/internal/ssa/gen/main.go
@@ -52,6 +52,7 @@
 	faultOnNilArg0    bool  // this op will fault if arg0 is nil (and aux encodes a small offset)
 	faultOnNilArg1    bool  // this op will fault if arg1 is nil (and aux encodes a small offset)
 	usesScratch       bool  // this op requires scratch memory space
+	hasSideEffects    bool  // for "reasons", not to be eliminated.  E.g., atomic store, #19182.
 }
 
 type blockData struct {
@@ -208,6 +209,9 @@
 			if v.usesScratch {
 				fmt.Fprintln(w, "usesScratch: true,")
 			}
+			if v.hasSideEffects {
+				fmt.Fprintln(w, "hasSideEffects: true,")
+			}
 			if a.name == "generic" {
 				fmt.Fprintln(w, "generic:true,")
 				fmt.Fprintln(w, "},") // close op
diff --git a/src/cmd/compile/internal/ssa/likelyadjust.go b/src/cmd/compile/internal/ssa/likelyadjust.go
index 38a5e81..a4e5534 100644
--- a/src/cmd/compile/internal/ssa/likelyadjust.go
+++ b/src/cmd/compile/internal/ssa/likelyadjust.go
@@ -33,13 +33,24 @@
 
 // outerinner records that outer contains inner
 func (sdom SparseTree) outerinner(outer, inner *loop) {
+	// There could be other outer loops found in some random order,
+	// locate the new outer loop appropriately among them.
 	oldouter := inner.outer
-	if oldouter == nil || sdom.isAncestorEq(oldouter.header, outer.header) {
-		inner.outer = outer
-		outer.isInner = false
-		if inner.containsCall {
-			outer.setContainsCall()
-		}
+	for oldouter != nil && sdom.isAncestor(outer.header, oldouter.header) {
+		inner = oldouter
+		oldouter = inner.outer
+	}
+	if outer == oldouter {
+		return
+	}
+	if oldouter != nil {
+		outer.outer = oldouter
+	}
+
+	inner.outer = outer
+	outer.isInner = false
+	if inner.containsCall {
+		outer.setContainsCall()
 	}
 }
 
diff --git a/src/cmd/compile/internal/ssa/loop_test.go b/src/cmd/compile/internal/ssa/loop_test.go
new file mode 100644
index 0000000..69a4962
--- /dev/null
+++ b/src/cmd/compile/internal/ssa/loop_test.go
@@ -0,0 +1,87 @@
+// Copyright 2017 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
+
+import (
+	"testing"
+)
+
+func TestLoopConditionS390X(t *testing.T) {
+	// Test that a simple loop condition does not generate a conditional
+	// move (issue #19227).
+	//
+	// MOVDLT is generated when Less64 is lowered but should be
+	// optimized into an LT branch.
+	//
+	// For example, compiling the following loop:
+	//
+	//   for i := 0; i < N; i++ {
+	//     sum += 3
+	//   }
+	//
+	// should generate assembly similar to:
+	//   loop:
+	//     CMP    R0, R1
+	//     BGE    done
+	//     ADD    $3, R4
+	//     ADD    $1, R1
+	//     BR     loop
+	//   done:
+	//
+	// rather than:
+	// loop:
+	//     MOVD   $0, R2
+	//     MOVD   $1, R3
+	//     CMP    R0, R1
+	//     MOVDLT R2, R3
+	//     CMPW   R2, $0
+	//     BNE    done
+	//     ADD    $3, R4
+	//     ADD    $1, R1
+	//     BR     loop
+	//   done:
+	//
+	c := testConfigS390X(t)
+	fun := Fun(c, "entry",
+		Bloc("entry",
+			Valu("mem", OpInitMem, TypeMem, 0, nil),
+			Valu("SP", OpSP, TypeUInt64, 0, nil),
+			Valu("Nptr", OpOffPtr, TypeInt64Ptr, 8, nil, "SP"),
+			Valu("ret", OpOffPtr, TypeInt64Ptr, 16, nil, "SP"),
+			Valu("N", OpLoad, TypeInt64, 0, nil, "Nptr", "mem"),
+			Valu("starti", OpConst64, TypeInt64, 0, nil),
+			Valu("startsum", OpConst64, TypeInt64, 0, nil),
+			Goto("b1")),
+		Bloc("b1",
+			Valu("phii", OpPhi, TypeInt64, 0, nil, "starti", "i"),
+			Valu("phisum", OpPhi, TypeInt64, 0, nil, "startsum", "sum"),
+			Valu("cmp1", OpLess64, TypeBool, 0, nil, "phii", "N"),
+			If("cmp1", "b2", "b3")),
+		Bloc("b2",
+			Valu("c1", OpConst64, TypeInt64, 1, nil),
+			Valu("i", OpAdd64, TypeInt64, 0, nil, "phii", "c1"),
+			Valu("c3", OpConst64, TypeInt64, 3, nil),
+			Valu("sum", OpAdd64, TypeInt64, 0, nil, "phisum", "c3"),
+			Goto("b1")),
+		Bloc("b3",
+			Valu("store", OpStore, TypeMem, 8, nil, "ret", "phisum", "mem"),
+			Exit("store")))
+	CheckFunc(fun.f)
+	Compile(fun.f)
+	CheckFunc(fun.f)
+
+	checkOpcodeCounts(t, fun.f, map[Op]int{
+		OpS390XMOVDLT:    0,
+		OpS390XMOVDGT:    0,
+		OpS390XMOVDLE:    0,
+		OpS390XMOVDGE:    0,
+		OpS390XMOVDEQ:    0,
+		OpS390XMOVDNE:    0,
+		OpS390XCMP:       1,
+		OpS390XCMPWconst: 0,
+	})
+
+	fun.f.Free()
+}
diff --git a/src/cmd/compile/internal/ssa/op.go b/src/cmd/compile/internal/ssa/op.go
index 4c3164f..37b2f74 100644
--- a/src/cmd/compile/internal/ssa/op.go
+++ b/src/cmd/compile/internal/ssa/op.go
@@ -34,6 +34,7 @@
 	faultOnNilArg0    bool // this op will fault if arg0 is nil (and aux encodes a small offset)
 	faultOnNilArg1    bool // this op will fault if arg1 is nil (and aux encodes a small offset)
 	usesScratch       bool // this op requires scratch memory space
+	hasSideEffects    bool // for "reasons", not to be eliminated.  E.g., atomic store, #19182.
 }
 
 type inputInfo struct {
diff --git a/src/cmd/compile/internal/ssa/opGen.go b/src/cmd/compile/internal/ssa/opGen.go
index 9d11d03..2938bd1 100644
--- a/src/cmd/compile/internal/ssa/opGen.go
+++ b/src/cmd/compile/internal/ssa/opGen.go
@@ -7307,6 +7307,7 @@
 		argLen:         3,
 		resultInArg0:   true,
 		faultOnNilArg1: true,
+		hasSideEffects: true,
 		asm:            x86.AXCHGL,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7324,6 +7325,7 @@
 		argLen:         3,
 		resultInArg0:   true,
 		faultOnNilArg1: true,
+		hasSideEffects: true,
 		asm:            x86.AXCHGQ,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7342,6 +7344,7 @@
 		resultInArg0:   true,
 		clobberFlags:   true,
 		faultOnNilArg1: true,
+		hasSideEffects: true,
 		asm:            x86.AXADDL,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7360,6 +7363,7 @@
 		resultInArg0:   true,
 		clobberFlags:   true,
 		faultOnNilArg1: true,
+		hasSideEffects: true,
 		asm:            x86.AXADDQ,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7387,6 +7391,7 @@
 		argLen:         4,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            x86.ACMPXCHGL,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7407,6 +7412,7 @@
 		argLen:         4,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            x86.ACMPXCHGQ,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7427,6 +7433,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            x86.AANDB,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7441,6 +7448,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            x86.AORB,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -10075,6 +10083,7 @@
 			inputs: []inputInfo{
 				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
 			},
+			clobbers: 2147483648, // F15
 			outputs: []outputInfo{
 				{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
 			},
@@ -10088,6 +10097,7 @@
 			inputs: []inputInfo{
 				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
 			},
+			clobbers: 2147483648, // F15
 			outputs: []outputInfo{
 				{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
 			},
@@ -10101,6 +10111,7 @@
 			inputs: []inputInfo{
 				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
 			},
+			clobbers: 2147483648, // F15
 			outputs: []outputInfo{
 				{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
 			},
@@ -10114,6 +10125,7 @@
 			inputs: []inputInfo{
 				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
 			},
+			clobbers: 2147483648, // F15
 			outputs: []outputInfo{
 				{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
 			},
@@ -10127,6 +10139,7 @@
 			inputs: []inputInfo{
 				{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
 			},
+			clobbers: 2147483648, // F15
 			outputs: []outputInfo{
 				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
 			},
@@ -10140,6 +10153,7 @@
 			inputs: []inputInfo{
 				{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
 			},
+			clobbers: 2147483648, // F15
 			outputs: []outputInfo{
 				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
 			},
@@ -10153,6 +10167,7 @@
 			inputs: []inputInfo{
 				{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
 			},
+			clobbers: 2147483648, // F15
 			outputs: []outputInfo{
 				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
 			},
@@ -10166,6 +10181,7 @@
 			inputs: []inputInfo{
 				{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
 			},
+			clobbers: 2147483648, // F15
 			outputs: []outputInfo{
 				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
 			},
@@ -12657,6 +12673,7 @@
 		name:           "STLR",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            arm64.ASTLR,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -12669,6 +12686,7 @@
 		name:           "STLRW",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            arm64.ASTLRW,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -12682,6 +12700,7 @@
 		argLen:          3,
 		resultNotInArgs: true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 805044223},           // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -12697,6 +12716,7 @@
 		argLen:          3,
 		resultNotInArgs: true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 805044223},           // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -12712,6 +12732,7 @@
 		argLen:          3,
 		resultNotInArgs: true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 805044223},           // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -12727,6 +12748,7 @@
 		argLen:          3,
 		resultNotInArgs: true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 805044223},           // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -12743,6 +12765,7 @@
 		resultNotInArgs: true,
 		clobberFlags:    true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 805044223},           // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -12760,6 +12783,7 @@
 		resultNotInArgs: true,
 		clobberFlags:    true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 805044223},           // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R19 R20 R21 R22 R23 R24 R25 R26 g R30
@@ -12775,6 +12799,7 @@
 		name:           "LoweredAtomicAnd8",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            arm64.AAND,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -12787,6 +12812,7 @@
 		name:           "LoweredAtomicOr8",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            arm64.AORR,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -13977,6 +14003,7 @@
 		name:           "LoweredAtomicStore",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 469762046},       // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
@@ -13988,6 +14015,7 @@
 		name:           "LoweredAtomicStorezero",
 		argLen:         2,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
@@ -13999,6 +14027,7 @@
 		argLen:          3,
 		resultNotInArgs: true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 469762046},       // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
@@ -14014,6 +14043,7 @@
 		argLen:          3,
 		resultNotInArgs: true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 469762046},       // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
@@ -14030,6 +14060,7 @@
 		argLen:          2,
 		resultNotInArgs: true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{0, 140738025226238}, // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 SP g R31 SB
@@ -14044,6 +14075,7 @@
 		argLen:          4,
 		resultNotInArgs: true,
 		faultOnNilArg0:  true,
+		hasSideEffects:  true,
 		reg: regInfo{
 			inputs: []inputInfo{
 				{1, 469762046},       // R1 R2 R3 R4 R5 R6 R7 R8 R9 R10 R11 R12 R13 R14 R15 R16 R17 R18 R19 R20 R21 R22 R24 R25 R28 g R31
@@ -14059,6 +14091,7 @@
 		name:           "LoweredAtomicAnd",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            mips.AAND,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -14071,6 +14104,7 @@
 		name:           "LoweredAtomicOr",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            mips.AOR,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19500,6 +19534,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.AMOVW,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19514,6 +19549,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.AMOVD,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19527,6 +19563,7 @@
 		auxType:        auxSymOff,
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ALAA,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19543,6 +19580,7 @@
 		auxType:        auxSymOff,
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ALAAG,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19570,6 +19608,7 @@
 		argLen:         4,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ACS,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19590,6 +19629,7 @@
 		argLen:         4,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ACSG,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19610,6 +19650,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ACS,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19628,6 +19669,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ACSG,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -21415,59 +21457,70 @@
 		generic: true,
 	},
 	{
-		name:    "AtomicStore32",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicStore32",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicStore64",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicStore64",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicStorePtrNoWB",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicStorePtrNoWB",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicExchange32",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicExchange32",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicExchange64",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicExchange64",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicAdd32",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicAdd32",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicAdd64",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicAdd64",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicCompareAndSwap32",
-		argLen:  4,
-		generic: true,
+		name:           "AtomicCompareAndSwap32",
+		argLen:         4,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicCompareAndSwap64",
-		argLen:  4,
-		generic: true,
+		name:           "AtomicCompareAndSwap64",
+		argLen:         4,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicAnd8",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicAnd8",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 	{
-		name:    "AtomicOr8",
-		argLen:  3,
-		generic: true,
+		name:           "AtomicOr8",
+		argLen:         3,
+		hasSideEffects: true,
+		generic:        true,
 	},
 }
 
diff --git a/src/cmd/compile/internal/ssa/rewriteARM.go b/src/cmd/compile/internal/ssa/rewriteARM.go
index 0f8a77f..234783b 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM.go
@@ -14517,7 +14517,7 @@
 	_ = b
 	// match: (Lrot16 <t> x [c])
 	// cond:
-	// result: (OR (SLLconst <t> x [c&15]) (SRLconst <t> x [16-c&15]))
+	// result: (OR (SLLconst <t> x [c&15]) (SRLconst <t> (ZeroExt16to32 x) [16-c&15]))
 	for {
 		t := v.Type
 		c := v.AuxInt
@@ -14529,7 +14529,9 @@
 		v.AddArg(v0)
 		v1 := b.NewValue0(v.Line, OpARMSRLconst, t)
 		v1.AuxInt = 16 - c&15
-		v1.AddArg(x)
+		v2 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
+		v2.AddArg(x)
+		v1.AddArg(v2)
 		v.AddArg(v1)
 		return true
 	}
@@ -14554,7 +14556,7 @@
 	_ = b
 	// match: (Lrot8 <t> x [c])
 	// cond:
-	// result: (OR (SLLconst <t> x [c&7]) (SRLconst <t> x [8-c&7]))
+	// result: (OR (SLLconst <t> x [c&7]) (SRLconst <t> (ZeroExt8to32 x) [8-c&7]))
 	for {
 		t := v.Type
 		c := v.AuxInt
@@ -14566,7 +14568,9 @@
 		v.AddArg(v0)
 		v1 := b.NewValue0(v.Line, OpARMSRLconst, t)
 		v1.AuxInt = 8 - c&7
-		v1.AddArg(x)
+		v2 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
+		v2.AddArg(x)
+		v1.AddArg(v2)
 		v.AddArg(v1)
 		return true
 	}
diff --git a/src/cmd/compile/internal/ssa/rewriteARM64.go b/src/cmd/compile/internal/ssa/rewriteARM64.go
index dd5aa28..5c49636 100644
--- a/src/cmd/compile/internal/ssa/rewriteARM64.go
+++ b/src/cmd/compile/internal/ssa/rewriteARM64.go
@@ -2625,7 +2625,7 @@
 	b := v.Block
 	_ = b
 	// match: (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (FMOVDload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -2637,7 +2637,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64FMOVDload)
@@ -2648,7 +2648,7 @@
 		return true
 	}
 	// match: (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -2661,7 +2661,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64FMOVDload)
@@ -2677,7 +2677,7 @@
 	b := v.Block
 	_ = b
 	// match: (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (FMOVDstore [off1+off2] {sym} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -2690,7 +2690,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64FMOVDstore)
@@ -2702,7 +2702,7 @@
 		return true
 	}
 	// match: (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -2716,7 +2716,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64FMOVDstore)
@@ -2733,7 +2733,7 @@
 	b := v.Block
 	_ = b
 	// match: (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (FMOVSload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -2745,7 +2745,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64FMOVSload)
@@ -2756,7 +2756,7 @@
 		return true
 	}
 	// match: (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -2769,7 +2769,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64FMOVSload)
@@ -2785,7 +2785,7 @@
 	b := v.Block
 	_ = b
 	// match: (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (FMOVSstore [off1+off2] {sym} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -2798,7 +2798,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64FMOVSstore)
@@ -2810,7 +2810,7 @@
 		return true
 	}
 	// match: (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -2824,7 +2824,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64FMOVSstore)
@@ -3511,7 +3511,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond:
+	// cond: is32Bit(off1+off2)
 	// result: (MOVBUload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -3523,6 +3523,9 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
+		if !(is32Bit(off1 + off2)) {
+			break
+		}
 		v.reset(OpARM64MOVBUload)
 		v.AuxInt = off1 + off2
 		v.Aux = sym
@@ -3531,7 +3534,7 @@
 		return true
 	}
 	// match: (MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2)
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2)
 	// result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -3544,7 +3547,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2)) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
 			break
 		}
 		v.reset(OpARM64MOVBUload)
@@ -3623,7 +3626,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVBload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond:
+	// cond: is32Bit(off1+off2)
 	// result: (MOVBload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -3635,6 +3638,9 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
+		if !(is32Bit(off1 + off2)) {
+			break
+		}
 		v.reset(OpARM64MOVBload)
 		v.AuxInt = off1 + off2
 		v.Aux = sym
@@ -3643,7 +3649,7 @@
 		return true
 	}
 	// match: (MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2)
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2)
 	// result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -3656,7 +3662,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2)) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
 			break
 		}
 		v.reset(OpARM64MOVBload)
@@ -3735,7 +3741,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	// cond:
+	// cond: is32Bit(off1+off2)
 	// result: (MOVBstore [off1+off2] {sym} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -3748,6 +3754,9 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
+		if !(is32Bit(off1 + off2)) {
+			break
+		}
 		v.reset(OpARM64MOVBstore)
 		v.AuxInt = off1 + off2
 		v.Aux = sym
@@ -3757,7 +3766,7 @@
 		return true
 	}
 	// match: (MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
-	// cond: canMergeSym(sym1,sym2)
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2)
 	// result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -3771,7 +3780,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !(canMergeSym(sym1, sym2)) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
 			break
 		}
 		v.reset(OpARM64MOVBstore)
@@ -3936,7 +3945,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond:
+	// cond: is32Bit(off1+off2)
 	// result: (MOVBstorezero [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -3948,6 +3957,9 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
+		if !(is32Bit(off1 + off2)) {
+			break
+		}
 		v.reset(OpARM64MOVBstorezero)
 		v.AuxInt = off1 + off2
 		v.Aux = sym
@@ -3956,7 +3968,7 @@
 		return true
 	}
 	// match: (MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2)
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2)
 	// result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -3969,7 +3981,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2)) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
 			break
 		}
 		v.reset(OpARM64MOVBstorezero)
@@ -3985,7 +3997,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVDload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -3997,7 +4009,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVDload)
@@ -4008,7 +4020,7 @@
 		return true
 	}
 	// match: (MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4021,7 +4033,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVDload)
@@ -4088,7 +4100,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVDstore [off1+off2] {sym} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -4101,7 +4113,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVDstore)
@@ -4113,7 +4125,7 @@
 		return true
 	}
 	// match: (MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -4127,7 +4139,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVDstore)
@@ -4166,7 +4178,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVDstorezero [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4178,7 +4190,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%2 == 8 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 8 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVDstorezero)
@@ -4189,7 +4201,7 @@
 		return true
 	}
 	// match: (MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4202,7 +4214,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVDstorezero)
@@ -4218,7 +4230,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVHUload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4230,7 +4242,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVHUload)
@@ -4241,7 +4253,7 @@
 		return true
 	}
 	// match: (MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4254,7 +4266,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVHUload)
@@ -4357,7 +4369,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVHload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4369,7 +4381,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVHload)
@@ -4380,7 +4392,7 @@
 		return true
 	}
 	// match: (MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4393,7 +4405,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVHload)
@@ -4520,7 +4532,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVHstore [off1+off2] {sym} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -4533,7 +4545,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVHstore)
@@ -4545,7 +4557,7 @@
 		return true
 	}
 	// match: (MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -4559,7 +4571,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVHstore)
@@ -4682,7 +4694,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVHstorezero [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4694,7 +4706,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVHstorezero)
@@ -4705,7 +4717,7 @@
 		return true
 	}
 	// match: (MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4718,7 +4730,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVHstorezero)
@@ -4734,7 +4746,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVWUload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4746,7 +4758,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVWUload)
@@ -4757,7 +4769,7 @@
 		return true
 	}
 	// match: (MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4770,7 +4782,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVWUload)
@@ -4897,7 +4909,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVWload [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4909,7 +4921,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVWload)
@@ -4920,7 +4932,7 @@
 		return true
 	}
 	// match: (MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -4933,7 +4945,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVWload)
@@ -5108,7 +5120,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
-	// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVWstore [off1+off2] {sym} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -5121,7 +5133,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVWstore)
@@ -5133,7 +5145,7 @@
 		return true
 	}
 	// match: (MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
 	for {
 		off1 := v.AuxInt
@@ -5147,7 +5159,7 @@
 		ptr := v_0.Args[0]
 		val := v.Args[1]
 		mem := v.Args[2]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVWstore)
@@ -5228,7 +5240,7 @@
 	b := v.Block
 	_ = b
 	// match: (MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
-	// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
+	// cond: is32Bit(off1+off2) && !isArg(sym) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
 	// result: (MOVWstorezero [off1+off2] {sym} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -5240,7 +5252,7 @@
 		off2 := v_0.AuxInt
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
+		if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
 			break
 		}
 		v.reset(OpARM64MOVWstorezero)
@@ -5251,7 +5263,7 @@
 		return true
 	}
 	// match: (MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
-	// cond: canMergeSym(sym1,sym2) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
+	// cond: canMergeSym(sym1,sym2) 	&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2)) 	&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2)))
 	// result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
 	for {
 		off1 := v.AuxInt
@@ -5264,7 +5276,7 @@
 		sym2 := v_0.Aux
 		ptr := v_0.Args[0]
 		mem := v.Args[1]
-		if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
+		if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2) && !isArg(mergeSym(sym1, sym2)) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(mergeSym(sym1, sym2)))) {
 			break
 		}
 		v.reset(OpARM64MOVWstorezero)
diff --git a/src/cmd/compile/internal/ssa/rewriteMIPS.go b/src/cmd/compile/internal/ssa/rewriteMIPS.go
index cbe9f1b..76eac5b 100644
--- a/src/cmd/compile/internal/ssa/rewriteMIPS.go
+++ b/src/cmd/compile/internal/ssa/rewriteMIPS.go
@@ -712,7 +712,7 @@
 	_ = b
 	// match: (AtomicAnd8  ptr val mem)
 	// cond: !config.BigEndian
-	// result: (LoweredAtomicAnd (AND <config.fe.TypeUInt32().PtrTo()> (MOVWconst [^3]) ptr) 		(OR <config.fe.TypeUInt32()> (SLL <config.fe.TypeUInt32()> (ZeroExt8to32 val) 			(SLLconst <config.fe.TypeUInt32()> [3] 				(ANDconst  <config.fe.TypeUInt32()> [3] ptr))) 		(NORconst [0] <config.fe.TypeUInt32()> (SLL <config.fe.TypeUInt32()> 			(MOVWconst [0xff]) (SLLconst <config.fe.TypeUInt32()> [3] 				(ANDconst <config.fe.TypeUInt32()> [3] 					(XORconst <config.fe.TypeUInt32()> [3] ptr)))))) mem)
+	// result: (LoweredAtomicAnd (AND <config.fe.TypeUInt32().PtrTo()> (MOVWconst [^3]) ptr) 		(OR <config.fe.TypeUInt32()> (SLL <config.fe.TypeUInt32()> (ZeroExt8to32 val) 			(SLLconst <config.fe.TypeUInt32()> [3] 				(ANDconst  <config.fe.TypeUInt32()> [3] ptr))) 		(NORconst [0] <config.fe.TypeUInt32()> (SLL <config.fe.TypeUInt32()> 			(MOVWconst [0xff]) (SLLconst <config.fe.TypeUInt32()> [3] 				(ANDconst <config.fe.TypeUInt32()> [3] ptr))))) mem)
 	for {
 		ptr := v.Args[0]
 		val := v.Args[1]
@@ -750,10 +750,7 @@
 		v10.AuxInt = 3
 		v11 := b.NewValue0(v.Line, OpMIPSANDconst, config.fe.TypeUInt32())
 		v11.AuxInt = 3
-		v12 := b.NewValue0(v.Line, OpMIPSXORconst, config.fe.TypeUInt32())
-		v12.AuxInt = 3
-		v12.AddArg(ptr)
-		v11.AddArg(v12)
+		v11.AddArg(ptr)
 		v10.AddArg(v11)
 		v8.AddArg(v10)
 		v7.AddArg(v8)
diff --git a/src/cmd/compile/internal/ssa/rewriteS390X.go b/src/cmd/compile/internal/ssa/rewriteS390X.go
index 0425ced..866cf50 100644
--- a/src/cmd/compile/internal/ssa/rewriteS390X.go
+++ b/src/cmd/compile/internal/ssa/rewriteS390X.go
@@ -524,6 +524,8 @@
 		return rewriteValueS390X_OpS390XMOVDload(v, config)
 	case OpS390XMOVDloadidx:
 		return rewriteValueS390X_OpS390XMOVDloadidx(v, config)
+	case OpS390XMOVDnop:
+		return rewriteValueS390X_OpS390XMOVDnop(v, config)
 	case OpS390XMOVDreg:
 		return rewriteValueS390X_OpS390XMOVDreg(v, config)
 	case OpS390XMOVDstore:
@@ -10195,9 +10197,68 @@
 	}
 	return false
 }
+func rewriteValueS390X_OpS390XMOVDnop(v *Value, config *Config) bool {
+	b := v.Block
+	_ = b
+	// match: (MOVDnop <t> x)
+	// cond: t.Compare(x.Type) == CMPeq
+	// result: x
+	for {
+		t := v.Type
+		x := v.Args[0]
+		if !(t.Compare(x.Type) == CMPeq) {
+			break
+		}
+		v.reset(OpCopy)
+		v.Type = x.Type
+		v.AddArg(x)
+		return true
+	}
+	// match: (MOVDnop (MOVDconst [c]))
+	// cond:
+	// result: (MOVDconst [c])
+	for {
+		v_0 := v.Args[0]
+		if v_0.Op != OpS390XMOVDconst {
+			break
+		}
+		c := v_0.AuxInt
+		v.reset(OpS390XMOVDconst)
+		v.AuxInt = c
+		return true
+	}
+	return false
+}
 func rewriteValueS390X_OpS390XMOVDreg(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
+	// match: (MOVDreg <t> x)
+	// cond: t.Compare(x.Type) == CMPeq
+	// result: x
+	for {
+		t := v.Type
+		x := v.Args[0]
+		if !(t.Compare(x.Type) == CMPeq) {
+			break
+		}
+		v.reset(OpCopy)
+		v.Type = x.Type
+		v.AddArg(x)
+		return true
+	}
+	// match: (MOVDreg (MOVDconst [c]))
+	// cond:
+	// result: (MOVDconst [c])
+	for {
+		v_0 := v.Args[0]
+		if v_0.Op != OpS390XMOVDconst {
+			break
+		}
+		c := v_0.AuxInt
+		v.reset(OpS390XMOVDconst)
+		v.AuxInt = c
+		return true
+	}
 	// match: (MOVDreg x)
 	// cond: x.Uses == 1
 	// result: (MOVDnop x)
@@ -18181,7 +18242,7 @@
 		}
 		// match: (If cond yes no)
 		// cond:
-		// result: (NE (CMPWconst [0] (MOVBZreg cond)) yes no)
+		// result: (NE (CMPWconst [0] (MOVBZreg <config.fe.TypeBool()> cond)) yes no)
 		for {
 			v := b.Control
 			_ = v
@@ -18191,7 +18252,7 @@
 			b.Kind = BlockS390XNE
 			v0 := b.NewValue0(v.Line, OpS390XCMPWconst, TypeFlags)
 			v0.AuxInt = 0
-			v1 := b.NewValue0(v.Line, OpS390XMOVBZreg, config.fe.TypeUInt64())
+			v1 := b.NewValue0(v.Line, OpS390XMOVBZreg, config.fe.TypeBool())
 			v1.AddArg(cond)
 			v0.AddArg(v1)
 			b.SetControl(v0)
diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go
index f2a89d82..a455a9a 100644
--- a/src/cmd/compile/internal/ssa/schedule.go
+++ b/src/cmd/compile/internal/ssa/schedule.go
@@ -14,6 +14,7 @@
 	ScoreMemory
 	ScoreDefault
 	ScoreFlags
+	ScoreSelectCall
 	ScoreControl // towards bottom of block
 )
 
@@ -110,10 +111,25 @@
 				// We want all the vardefs next.
 				score[v.ID] = ScoreVarDef
 			case v.Type.IsMemory():
-				// Schedule stores as early as possible. This tends to
-				// reduce register pressure. It also helps make sure
-				// VARDEF ops are scheduled before the corresponding LEA.
-				score[v.ID] = ScoreMemory
+				// Don't schedule independent operations after call to those functions.
+				// runtime.selectgo will jump to next instruction after this call,
+				// causing extra execution of those operations. Prevent it, by setting
+				// priority to high value.
+				if (v.Op == OpAMD64CALLstatic || v.Op == OpPPC64CALLstatic ||
+					v.Op == OpARMCALLstatic || v.Op == OpARM64CALLstatic ||
+					v.Op == Op386CALLstatic || v.Op == OpMIPS64CALLstatic ||
+					v.Op == OpS390XCALLstatic || v.Op == OpMIPSCALLstatic) &&
+					(isSameSym(v.Aux, "runtime.selectrecv") ||
+						isSameSym(v.Aux, "runtime.selectrecv2") ||
+						isSameSym(v.Aux, "runtime.selectsend") ||
+						isSameSym(v.Aux, "runtime.selectdefault")) {
+					score[v.ID] = ScoreSelectCall
+				} else {
+					// Schedule stores as early as possible. This tends to
+					// reduce register pressure. It also helps make sure
+					// VARDEF ops are scheduled before the corresponding LEA.
+					score[v.ID] = ScoreMemory
+				}
 			case v.Op == OpSelect0 || v.Op == OpSelect1:
 				// Schedule the pseudo-op of reading part of a tuple
 				// immediately after the tuple-generating op, since
diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go
index 1185507..b6e6c77 100644
--- a/src/cmd/compile/internal/syntax/parser.go
+++ b/src/cmd/compile/internal/syntax/parser.go
@@ -1635,6 +1635,8 @@
 	return body
 }
 
+var dummyCond = &Name{Value: "false"}
+
 func (p *parser) header(forStmt bool) (init SimpleStmt, cond Expr, post SimpleStmt) {
 	if p.tok == _Lbrace {
 		return
@@ -1681,7 +1683,8 @@
 	case *ExprStmt:
 		cond = s.X
 	default:
-		p.error("invalid condition, tag, or type switch guard")
+		p.syntax_error(fmt.Sprintf("%s used as value", String(s)))
+		cond = dummyCond // avoid follow-up error for if statements
 	}
 
 	p.xnest = outer
diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go
index 1d7677c..6fb4235 100644
--- a/src/cmd/go/get.go
+++ b/src/cmd/go/get.go
@@ -428,7 +428,7 @@
 			return fmt.Errorf("cannot download, $GOPATH not set. For more details see: 'go help gopath'")
 		}
 		// Guard against people setting GOPATH=$GOROOT.
-		if list[0] == goroot {
+		if filepath.Clean(list[0]) == filepath.Clean(goroot) {
 			return fmt.Errorf("cannot download, $GOPATH must not be set to $GOROOT. For more details see: 'go help gopath'")
 		}
 		if _, err := os.Stat(filepath.Join(list[0], "src/cmd/go/alldocs.go")); err == nil {
diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go
index ef5348b..fa78578d 100644
--- a/src/cmd/go/go_test.go
+++ b/src/cmd/go/go_test.go
@@ -1683,173 +1683,111 @@
 	}
 }
 
-// Test go env missing GOPATH shows default.
-func TestMissingGOPATHEnvShowsDefault(t *testing.T) {
+func TestDefaultGOPATH(t *testing.T) {
 	tg := testgo(t)
 	defer tg.cleanup()
 	tg.parallel()
-	tg.setenv("GOPATH", "")
+	tg.tempDir("home/go")
+	tg.setenv(homeEnvName(), tg.path("home"))
+
 	tg.run("env", "GOPATH")
+	tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
 
-	want := filepath.Join(os.Getenv(homeEnvName()), "go")
-	got := strings.TrimSpace(tg.getStdout())
-	if got != want {
-		t.Errorf("got %q; want %q", got, want)
-	}
+	tg.setenv("GOROOT", tg.path("home/go"))
+	tg.run("env", "GOPATH")
+	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
+
+	tg.setenv("GOROOT", tg.path("home/go")+"/")
+	tg.run("env", "GOPATH")
+	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go/")
 }
 
-// Test go get missing GOPATH causes go get to warn if directory doesn't exist.
-func TestMissingGOPATHGetWarnsIfNotExists(t *testing.T) {
+func TestDefaultGOPATHGet(t *testing.T) {
 	testenv.MustHaveExternalNetwork(t)
 
-	if _, err := exec.LookPath("git"); err != nil {
-		t.Skip("skipping because git binary not found")
-	}
-
 	tg := testgo(t)
 	defer tg.cleanup()
-
-	// setenv variables for test and defer deleting temporary home directory.
 	tg.setenv("GOPATH", "")
-	tmp, err := ioutil.TempDir("", "")
-	if err != nil {
-		t.Fatalf("could not create tmp home: %v", err)
-	}
-	defer os.RemoveAll(tmp)
-	tg.setenv(homeEnvName(), tmp)
+	tg.tempDir("home")
+	tg.setenv(homeEnvName(), tg.path("home"))
 
+	// warn for creating directory
 	tg.run("get", "-v", "github.com/golang/example/hello")
+	tg.grepStderr("created GOPATH="+regexp.QuoteMeta(tg.path("home/go"))+"; see 'go help gopath'", "did not create GOPATH")
 
-	want := fmt.Sprintf("created GOPATH=%s; see 'go help gopath'", filepath.Join(tmp, "go"))
-	got := strings.TrimSpace(tg.getStderr())
-	if !strings.Contains(got, want) {
-		t.Errorf("got %q; want %q", got, want)
-	}
-}
-
-// Test go get missing GOPATH causes no warning if directory exists.
-func TestMissingGOPATHGetDoesntWarnIfExists(t *testing.T) {
-	testenv.MustHaveExternalNetwork(t)
-
-	if _, err := exec.LookPath("git"); err != nil {
-		t.Skip("skipping because git binary not found")
-	}
-
-	tg := testgo(t)
-	defer tg.cleanup()
-
-	// setenv variables for test and defer resetting them.
-	tg.setenv("GOPATH", "")
-	tmp, err := ioutil.TempDir("", "")
-	if err != nil {
-		t.Fatalf("could not create tmp home: %v", err)
-	}
-	defer os.RemoveAll(tmp)
-	if err := os.Mkdir(filepath.Join(tmp, "go"), 0777); err != nil {
-		t.Fatalf("could not create $HOME/go: %v", err)
-	}
-
-	tg.setenv(homeEnvName(), tmp)
-
+	// no warning if directory already exists
+	tg.must(os.RemoveAll(tg.path("home/go")))
+	tg.tempDir("home/go")
 	tg.run("get", "github.com/golang/example/hello")
+	tg.grepStderrNot(".", "expected no output on standard error")
 
-	got := strings.TrimSpace(tg.getStderr())
-	if got != "" {
-		t.Errorf("got %q; wants empty", got)
-	}
+	// error if $HOME/go is a file
+	tg.must(os.RemoveAll(tg.path("home/go")))
+	tg.tempFile("home/go", "")
+	tg.runFail("get", "github.com/golang/example/hello")
+	tg.grepStderr(`mkdir .*[/\\]go: .*(not a directory|cannot find the path)`, "expected error because $HOME/go is a file")
 }
 
-// Test go get missing GOPATH fails if pointed file is not a directory.
-func TestMissingGOPATHGetFailsIfItsNotDirectory(t *testing.T) {
-	testenv.MustHaveExternalNetwork(t)
-
+func TestDefaultGOPATHPrintedSearchList(t *testing.T) {
 	tg := testgo(t)
 	defer tg.cleanup()
-
-	// setenv variables for test and defer resetting them.
 	tg.setenv("GOPATH", "")
-	tmp, err := ioutil.TempDir("", "")
-	if err != nil {
-		t.Fatalf("could not create tmp home: %v", err)
-	}
-	defer os.RemoveAll(tmp)
+	tg.tempDir("home")
+	tg.setenv(homeEnvName(), tg.path("home"))
 
-	path := filepath.Join(tmp, "go")
-	if err := ioutil.WriteFile(path, nil, 0777); err != nil {
-		t.Fatalf("could not create GOPATH at %s: %v", path, err)
-	}
-	tg.setenv(homeEnvName(), tmp)
-
-	const pkg = "github.com/golang/example/hello"
-	tg.runFail("get", pkg)
-
-	msg := "not a directory"
-	if runtime.GOOS == "windows" {
-		msg = "The system cannot find the path specified."
-	}
-	want := fmt.Sprintf("package %s: mkdir %s: %s", pkg, filepath.Join(tmp, "go"), msg)
-	got := strings.TrimSpace(tg.getStderr())
-	if got != want {
-		t.Errorf("got %q; wants %q", got, want)
-	}
-}
-
-// Test go install of missing package when missing GOPATH fails and shows default GOPATH.
-func TestMissingGOPATHInstallMissingPackageFailsAndShowsDefault(t *testing.T) {
-	tg := testgo(t)
-	defer tg.cleanup()
-
-	// setenv variables for test and defer resetting them.
-	tg.setenv("GOPATH", "")
-	tmp, err := ioutil.TempDir("", "")
-	if err != nil {
-		t.Fatalf("could not create tmp home: %v", err)
-	}
-	defer os.RemoveAll(tmp)
-	if err := os.Mkdir(filepath.Join(tmp, "go"), 0777); err != nil {
-		t.Fatalf("could not create $HOME/go: %v", err)
-	}
-	tg.setenv(homeEnvName(), tmp)
-
-	const pkg = "github.com/golang/example/hello"
-	tg.runFail("install", pkg)
-
-	pkgPath := filepath.Join(strings.Split(pkg, "/")...)
-	want := fmt.Sprintf("can't load package: package %s: cannot find package \"%s\" in any of:", pkg, pkg) +
-		fmt.Sprintf("\n\t%s (from $GOROOT)", filepath.Join(runtime.GOROOT(), "src", pkgPath)) +
-		fmt.Sprintf("\n\t%s (from $GOPATH)", filepath.Join(tmp, "go", "src", pkgPath))
-
-	got := strings.TrimSpace(tg.getStderr())
-	if got != want {
-		t.Errorf("got %q; wants %q", got, want)
-	}
+	tg.runFail("install", "github.com/golang/example/hello")
+	tg.grepStderr(regexp.QuoteMeta(tg.path("home/go/src/github.com/golang/example/hello"))+`.*from \$GOPATH`, "expected default GOPATH")
 }
 
 // Issue 4186.  go get cannot be used to download packages to $GOROOT.
 // Test that without GOPATH set, go get should fail.
-func TestWithoutGOPATHGoGetFails(t *testing.T) {
+func TestGoGetIntoGOROOT(t *testing.T) {
 	testenv.MustHaveExternalNetwork(t)
 
 	tg := testgo(t)
 	defer tg.cleanup()
 	tg.parallel()
 	tg.tempDir("src")
-	tg.setenv("GOPATH", "")
-	tg.setenv("GOROOT", tg.path("."))
-	tg.runFail("get", "-d", "golang.org/x/codereview/cmd/hgpatch")
-}
 
-// Test that with GOPATH=$GOROOT, go get should fail.
-func TestWithGOPATHEqualsGOROOTGoGetFails(t *testing.T) {
-	testenv.MustHaveExternalNetwork(t)
-
-	tg := testgo(t)
-	defer tg.cleanup()
-	tg.parallel()
-	tg.tempDir("src")
+	// Fails because GOROOT=GOPATH
 	tg.setenv("GOPATH", tg.path("."))
 	tg.setenv("GOROOT", tg.path("."))
-	tg.runFail("get", "-d", "golang.org/x/codereview/cmd/hgpatch")
+	tg.runFail("get", "-d", "github.com/golang/example/hello")
+	tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
+	tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
+
+	// Fails because GOROOT=GOPATH after cleaning.
+	tg.setenv("GOPATH", tg.path(".")+"/")
+	tg.setenv("GOROOT", tg.path("."))
+	tg.runFail("get", "-d", "github.com/golang/example/hello")
+	tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
+	tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
+
+	tg.setenv("GOPATH", tg.path("."))
+	tg.setenv("GOROOT", tg.path(".")+"/")
+	tg.runFail("get", "-d", "github.com/golang/example/hello")
+	tg.grepStderr("warning: GOPATH set to GOROOT", "go should detect GOPATH=GOROOT")
+	tg.grepStderr(`\$GOPATH must not be set to \$GOROOT`, "go should detect GOPATH=GOROOT")
+
+	// Fails because GOROOT=$HOME/go so default GOPATH unset.
+	tg.tempDir("home/go")
+	tg.setenv(homeEnvName(), tg.path("home"))
+	tg.setenv("GOPATH", "")
+	tg.setenv("GOROOT", tg.path("home/go"))
+	tg.runFail("get", "-d", "github.com/golang/example/hello")
+	tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
+
+	tg.setenv(homeEnvName(), tg.path("home")+"/")
+	tg.setenv("GOPATH", "")
+	tg.setenv("GOROOT", tg.path("home/go"))
+	tg.runFail("get", "-d", "github.com/golang/example/hello")
+	tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
+
+	tg.setenv(homeEnvName(), tg.path("home"))
+	tg.setenv("GOPATH", "")
+	tg.setenv("GOROOT", tg.path("home/go")+"/")
+	tg.runFail("get", "-d", "github.com/golang/example/hello")
+	tg.grepStderr(`\$GOPATH not set`, "expected GOPATH not set")
 }
 
 func TestLdflagsArgumentsWithSpacesIssue3941(t *testing.T) {
@@ -2289,6 +2227,24 @@
 	}
 }
 
+func TestTestRaceInstall(t *testing.T) {
+	if !canRace {
+		t.Skip("no race detector")
+	}
+
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
+
+	tg.tempDir("pkg")
+	pkgdir := tg.path("pkg")
+	tg.run("install", "-race", "-pkgdir="+pkgdir, "std")
+	tg.run("test", "-race", "-pkgdir="+pkgdir, "-i", "-v", "empty/pkg")
+	if tg.getStderr() != "" {
+		t.Error("go test -i -race: rebuilds cached packages")
+	}
+}
+
 func TestBuildDryRunWithCgo(t *testing.T) {
 	if !canCgo {
 		t.Skip("skipping because cgo not enabled")
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index 07fc4e2..d80ff2d 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -136,7 +136,7 @@
 	// Diagnose common mistake: GOPATH==GOROOT.
 	// This setting is equivalent to not setting GOPATH at all,
 	// which is not what most people want when they do it.
-	if gopath := buildContext.GOPATH; gopath == runtime.GOROOT() {
+	if gopath := buildContext.GOPATH; filepath.Clean(gopath) == filepath.Clean(runtime.GOROOT()) {
 		fmt.Fprintf(os.Stderr, "warning: GOPATH set to GOROOT (%s) has no effect\n", gopath)
 	} else {
 		for _, p := range filepath.SplitList(gopath) {
diff --git a/src/cmd/go/pkg.go b/src/cmd/go/pkg.go
index e40f942..575f187 100644
--- a/src/cmd/go/pkg.go
+++ b/src/cmd/go/pkg.go
@@ -955,10 +955,6 @@
 		if p.Name == "main" && goarch == "arm" {
 			importPaths = append(importPaths, "math")
 		}
-		// In coverage atomic mode everything depends on sync/atomic.
-		if testCoverMode == "atomic" && (!p.Standard || (p.ImportPath != "runtime/cgo" && p.ImportPath != "runtime/race" && p.ImportPath != "sync/atomic")) {
-			importPaths = append(importPaths, "sync/atomic")
-		}
 	}
 
 	// Runtime and its internal packages depend on runtime/internal/sys,
diff --git a/src/cmd/go/test.go b/src/cmd/go/test.go
index 6482f0f..35250c9 100644
--- a/src/cmd/go/test.go
+++ b/src/cmd/go/test.go
@@ -545,6 +545,10 @@
 
 	// Prepare build + run + print actions for all packages being tested.
 	for _, p := range pkgs {
+		// sync/atomic import is inserted by the cover tool. See #18486
+		if testCover && testCoverMode == "atomic" {
+			ensureImport(p, "sync/atomic")
+		}
 		buildTest, runTest, printTest, err := b.test(p)
 		if err != nil {
 			str := err.Error()
@@ -636,6 +640,23 @@
 	b.do(root)
 }
 
+// ensures that package p imports the named package.
+func ensureImport(p *Package, pkg string) {
+	for _, d := range p.deps {
+		if d.Name == pkg {
+			return
+		}
+	}
+
+	a := loadPackage(pkg, &importStack{})
+	if a.Error != nil {
+		fatalf("load %s: %v", pkg, a.Error)
+	}
+	computeStale(a)
+
+	p.imports = append(p.imports, a)
+}
+
 func contains(x []string, s string) bool {
 	for _, t := range x {
 		if t == s {
diff --git a/src/cmd/link/dwarf_test.go b/src/cmd/link/dwarf_test.go
new file mode 100644
index 0000000..32fa3a3
--- /dev/null
+++ b/src/cmd/link/dwarf_test.go
@@ -0,0 +1,125 @@
+// Copyright 2017 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 main
+
+import (
+	"cmd/internal/objfile"
+	"debug/dwarf"
+	"internal/testenv"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path"
+	"path/filepath"
+	"runtime"
+	"strings"
+	"testing"
+)
+
+func TestDWARF(t *testing.T) {
+	if runtime.GOOS == "windows" {
+		t.Skip("DWARF is not supported on Windows")
+	}
+
+	testenv.MustHaveCGO(t)
+	testenv.MustHaveGoBuild(t)
+
+	if runtime.GOOS == "plan9" {
+		t.Skip("skipping on plan9; no DWARF symbol table in executables")
+	}
+
+	out, err := exec.Command(testenv.GoToolPath(t), "list", "-f", "{{.Stale}}", "cmd/link").CombinedOutput()
+	if err != nil {
+		t.Fatalf("go list: %v\n%s", err, out)
+	}
+	if string(out) != "false\n" {
+		t.Fatalf("cmd/link is stale - run go install cmd/link")
+	}
+
+	tmpDir, err := ioutil.TempDir("", "go-link-TestDWARF")
+	if err != nil {
+		t.Fatal("TempDir failed: ", err)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	for _, prog := range []string{"testprog", "testprogcgo"} {
+		t.Run(prog, func(t *testing.T) {
+			exe := filepath.Join(tmpDir, prog+".exe")
+			dir := "../../runtime/testdata/" + prog
+			out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", exe, dir).CombinedOutput()
+			if err != nil {
+				t.Fatalf("go build -o %v %v: %v\n%s", exe, dir, err, out)
+			}
+
+			f, err := objfile.Open(exe)
+			if err != nil {
+				t.Fatal(err)
+			}
+			defer f.Close()
+
+			syms, err := f.Symbols()
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			var addr uint64
+			for _, sym := range syms {
+				if sym.Name == "main.main" {
+					addr = sym.Addr
+					break
+				}
+			}
+			if addr == 0 {
+				t.Fatal("cannot find main.main in symbols")
+			}
+
+			d, err := f.DWARF()
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			// TODO: We'd like to use filepath.Join here.
+			// Also related: golang.org/issue/19784.
+			wantFile := path.Join(prog, "main.go")
+			wantLine := 24
+			r := d.Reader()
+			var line dwarf.LineEntry
+			for {
+				cu, err := r.Next()
+				if err != nil {
+					t.Fatal(err)
+				}
+				if cu == nil {
+					break
+				}
+				if cu.Tag != dwarf.TagCompileUnit {
+					r.SkipChildren()
+					continue
+				}
+				lr, err := d.LineReader(cu)
+				if err != nil {
+					t.Fatal(err)
+				}
+				for {
+					err := lr.Next(&line)
+					if err == io.EOF {
+						break
+					}
+					if err != nil {
+						t.Fatal(err)
+					}
+					if line.Address == addr {
+						if !strings.HasSuffix(line.File.Name, wantFile) || line.Line != wantLine {
+							t.Errorf("%#x is %s:%d, want %s:%d", addr, line.File.Name, line.Line, filepath.Join("...", wantFile), wantLine)
+						}
+						return
+					}
+				}
+			}
+			t.Fatalf("did not find file:line for %#x (main.main)", addr)
+		})
+	}
+}
diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go
index 7d00ff1..2656c24 100644
--- a/src/cmd/link/internal/ld/config.go
+++ b/src/cmd/link/internal/ld/config.go
@@ -238,6 +238,8 @@
 				Linkmode = LinkExternal
 			} else if iscgo && externalobj {
 				Linkmode = LinkExternal
+			} else if Buildmode == BuildmodePIE {
+				Linkmode = LinkExternal // https://golang.org/issue/18968
 			} else {
 				Linkmode = LinkInternal
 			}
diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go
index 74d79d3..b624aa0 100644
--- a/src/cmd/link/internal/ld/lib.go
+++ b/src/cmd/link/internal/ld/lib.go
@@ -430,6 +430,10 @@
 	// We now have enough information to determine the link mode.
 	determineLinkMode(ctxt)
 
+	if Headtype == obj.Hdarwin && Linkmode == LinkExternal {
+		*FlagTextAddr = 0
+	}
+
 	if Linkmode == LinkExternal && SysArch.Family == sys.PPC64 {
 		toc := ctxt.Syms.Lookup(".TOC.", 0)
 		toc.Type = obj.SDYNIMPORT
@@ -998,6 +1002,10 @@
 
 	if !*FlagS && !debug_s {
 		argv = append(argv, "-gdwarf-2")
+	} else if Headtype == obj.Hdarwin {
+		// Recent versions of macOS print
+		//	ld: warning: option -s is obsolete and being ignored
+		// so do not pass any arguments.
 	} else {
 		argv = append(argv, "-s")
 	}
@@ -1219,7 +1227,7 @@
 		l.Logf("%s", out)
 	}
 
-	if !*FlagS && !debug_s && Headtype == obj.Hdarwin {
+	if !*FlagS && !*FlagW && !debug_s && Headtype == obj.Hdarwin {
 		// Skip combining dwarf on arm.
 		if !SysArch.InFamily(sys.ARM, sys.ARM64) {
 			dsym := filepath.Join(*flagTmpdir, "go.dwarf")
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index f3687da..1ab61b7 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -449,7 +449,7 @@
 			ms.filesize = Segdata.Fileoff + Segdata.Filelen - Segtext.Fileoff
 		} else {
 			ms.filesize = Segdwarf.Fileoff + Segdwarf.Filelen - Segtext.Fileoff
-			ms.vsize = ms.filesize
+			ms.vsize = Segdwarf.Vaddr + Segdwarf.Length - Segtext.Vaddr
 		}
 	}
 
diff --git a/src/cmd/link/internal/ld/macho_combine_dwarf.go b/src/cmd/link/internal/ld/macho_combine_dwarf.go
index dcc371e..8c6c4a8 100644
--- a/src/cmd/link/internal/ld/macho_combine_dwarf.go
+++ b/src/cmd/link/internal/ld/macho_combine_dwarf.go
@@ -17,6 +17,7 @@
 
 var realdwarf, linkseg *macho.Segment
 var dwarfstart, linkstart int64
+var dwarfaddr, linkaddr int64
 var linkoffset uint32
 
 const (
@@ -41,8 +42,7 @@
 	LC_DYLIB_CODE_SIGN_DRS  = 0x2B
 	LC_ENCRYPTION_INFO_64   = 0x2C
 
-	dwarfMinAlign = 6  // 64 = 1 << 6
-	pageAlign     = 12 // 4096 = 1 << 12
+	pageAlign = 12 // 4096 = 1 << 12
 )
 
 type loadCmd struct {
@@ -157,16 +157,13 @@
 	}
 
 	// Now copy the dwarf data into the output.
-	maxalign := uint32(dwarfMinAlign) //
-	for _, sect := range dwarfm.Sections {
-		if sect.Align > maxalign {
-			maxalign = sect.Align
-		}
-	}
-	dwarfstart = machoCalcStart(realdwarf.Offset, linkseg.Offset, maxalign)
+	// Kernel requires all loaded segments to be page-aligned in the file,
+	// even though we mark this one as being 0 bytes of virtual address space.
+	dwarfstart = machoCalcStart(realdwarf.Offset, linkseg.Offset, pageAlign)
 	if _, err = outf.Seek(dwarfstart, 0); err != nil {
 		return err
 	}
+	dwarfaddr = int64((linkseg.Addr + linkseg.Memsz + 1<<pageAlign - 1) &^ (1<<pageAlign - 1))
 
 	if _, err = dwarff.Seek(int64(realdwarf.Offset), 0); err != nil {
 		return err
@@ -277,10 +274,10 @@
 		return err
 	}
 	// There shouldn't be any sections, but just to make sure...
-	return machoUpdateSections(r, segValue, reflect.ValueOf(sect), uint64(linkoffset))
+	return machoUpdateSections(r, segValue, reflect.ValueOf(sect), uint64(linkoffset), 0)
 }
 
-func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, delta uint64) error {
+func machoUpdateSections(r loadCmdReader, seg, sect reflect.Value, deltaOffset, deltaAddr uint64) error {
 	iseg := reflect.Indirect(seg)
 	nsect := iseg.FieldByName("Nsect").Uint()
 	if nsect == 0 {
@@ -291,16 +288,20 @@
 	isect := reflect.Indirect(sect)
 	offsetField := isect.FieldByName("Offset")
 	reloffField := isect.FieldByName("Reloff")
+	addrField := isect.FieldByName("Addr")
 	sectSize := int64(isect.Type().Size())
 	for i := uint64(0); i < nsect; i++ {
 		if err := r.ReadAt(sectOffset, sect.Interface()); err != nil {
 			return err
 		}
 		if offsetField.Uint() != 0 {
-			offsetField.SetUint(offsetField.Uint() + delta)
+			offsetField.SetUint(offsetField.Uint() + deltaOffset)
 		}
 		if reloffField.Uint() != 0 {
-			reloffField.SetUint(reloffField.Uint() + delta)
+			reloffField.SetUint(reloffField.Uint() + deltaOffset)
+		}
+		if addrField.Uint() != 0 {
+			addrField.SetUint(addrField.Uint() + deltaAddr)
 		}
 		if err := r.WriteAt(sectOffset, sect.Interface()); err != nil {
 			return err
@@ -327,15 +328,30 @@
 	if err := r.ReadAt(0, seg); err != nil {
 		return err
 	}
-	segValue := reflect.ValueOf(seg)
-	offset := reflect.Indirect(segValue).FieldByName("Offset")
+	segv := reflect.ValueOf(seg).Elem()
 
-	delta := uint64(dwarfstart) - realdwarf.Offset
-	offset.SetUint(offset.Uint() + delta)
+	segv.FieldByName("Offset").SetUint(uint64(dwarfstart))
+	segv.FieldByName("Addr").SetUint(uint64(dwarfaddr))
+
+	deltaOffset := uint64(dwarfstart) - realdwarf.Offset
+	deltaAddr := uint64(dwarfaddr) - realdwarf.Addr
+
+	// If we set Memsz to 0 (and might as well set Addr too),
+	// then the xnu kernel will bail out halfway through load_segment
+	// and not apply further sanity checks that we might fail in the future.
+	// We don't need the DWARF information actually available in memory.
+	// But if we do this for buildmode=c-shared then the user-space
+	// dynamic loader complains about memsz < filesz. Sigh.
+	if Buildmode != BuildmodeCShared {
+		segv.FieldByName("Addr").SetUint(0)
+		segv.FieldByName("Memsz").SetUint(0)
+		deltaAddr = 0
+	}
+
 	if err := r.WriteAt(0, seg); err != nil {
 		return err
 	}
-	return machoUpdateSections(*r, segValue, reflect.ValueOf(sect), delta)
+	return machoUpdateSections(*r, segv, reflect.ValueOf(sect), deltaOffset, deltaAddr)
 }
 
 func machoUpdateLoadCommand(r loadCmdReader, cmd interface{}, fields ...string) error {
diff --git a/src/cmd/link/internal/ppc64/asm.go b/src/cmd/link/internal/ppc64/asm.go
index 97107b9..cf2c532 100644
--- a/src/cmd/link/internal/ppc64/asm.go
+++ b/src/cmd/link/internal/ppc64/asm.go
@@ -87,6 +87,7 @@
 	//
 	// This assumes "case 1" from the ABI, where the caller needs
 	// us to save and restore the TOC pointer.
+	var stubs []*ld.Symbol
 	for _, s := range ctxt.Textp {
 		for i := range s.R {
 			r := &s.R[i]
@@ -108,7 +109,7 @@
 			if stub.Size == 0 {
 				// Need outer to resolve .TOC.
 				stub.Outer = s
-				ctxt.Textp = append(ctxt.Textp, stub)
+				stubs = append(stubs, stub)
 				gencallstub(ctxt, 1, stub, r.Sym)
 			}
 
@@ -121,6 +122,11 @@
 			ctxt.Arch.ByteOrder.PutUint32(s.P[r.Off+4:], o1)
 		}
 	}
+	// Put call stubs at the beginning (instead of the end).
+	// So when resolving the relocations to calls to the stubs,
+	// the addresses are known and trampolines can be inserted
+	// when necessary.
+	ctxt.Textp = append(stubs, ctxt.Textp...)
 }
 
 func genaddmoduledata(ctxt *ld.Link) {
diff --git a/src/cmd/link/linkbig_test.go b/src/cmd/link/linkbig_test.go
index d793c2f..960d89f 100644
--- a/src/cmd/link/linkbig_test.go
+++ b/src/cmd/link/linkbig_test.go
@@ -21,7 +21,7 @@
 
 func TestLargeText(t *testing.T) {
 	if testing.Short() || (obj.GOARCH != "ppc64le" && obj.GOARCH != "ppc64" && obj.GOARCH != "arm") {
-		t.Skip("Skipping large text section test in short mode or on %s", obj.GOARCH)
+		t.Skipf("Skipping large text section test in short mode or on %s", obj.GOARCH)
 	}
 	testenv.MustHaveGoBuild(t)
 
diff --git a/src/crypto/tls/common.go b/src/crypto/tls/common.go
index 276d176..de833a9 100644
--- a/src/crypto/tls/common.go
+++ b/src/crypto/tls/common.go
@@ -563,6 +563,7 @@
 		Certificates:                c.Certificates,
 		NameToCertificate:           c.NameToCertificate,
 		GetCertificate:              c.GetCertificate,
+		GetClientCertificate:        c.GetClientCertificate,
 		GetConfigForClient:          c.GetConfigForClient,
 		VerifyPeerCertificate:       c.VerifyPeerCertificate,
 		RootCAs:                     c.RootCAs,
diff --git a/src/crypto/tls/tls_test.go b/src/crypto/tls/tls_test.go
index 8933f4f..86812f0 100644
--- a/src/crypto/tls/tls_test.go
+++ b/src/crypto/tls/tls_test.go
@@ -13,13 +13,11 @@
 	"io"
 	"io/ioutil"
 	"math"
-	"math/rand"
 	"net"
 	"os"
 	"reflect"
 	"strings"
 	"testing"
-	"testing/quick"
 	"time"
 )
 
@@ -568,11 +566,50 @@
 	}
 }
 
-func TestClone(t *testing.T) {
+func TestCloneFuncFields(t *testing.T) {
+	const expectedCount = 5
+	called := 0
+
+	c1 := Config{
+		Time: func() time.Time {
+			called |= 1 << 0
+			return time.Time{}
+		},
+		GetCertificate: func(*ClientHelloInfo) (*Certificate, error) {
+			called |= 1 << 1
+			return nil, nil
+		},
+		GetClientCertificate: func(*CertificateRequestInfo) (*Certificate, error) {
+			called |= 1 << 2
+			return nil, nil
+		},
+		GetConfigForClient: func(*ClientHelloInfo) (*Config, error) {
+			called |= 1 << 3
+			return nil, nil
+		},
+		VerifyPeerCertificate: func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error {
+			called |= 1 << 4
+			return nil
+		},
+	}
+
+	c2 := c1.Clone()
+
+	c2.Time()
+	c2.GetCertificate(nil)
+	c2.GetClientCertificate(nil)
+	c2.GetConfigForClient(nil)
+	c2.VerifyPeerCertificate(nil, nil)
+
+	if called != (1<<expectedCount)-1 {
+		t.Fatalf("expected %d calls but saw calls %b", expectedCount, called)
+	}
+}
+
+func TestCloneNonFuncFields(t *testing.T) {
 	var c1 Config
 	v := reflect.ValueOf(&c1).Elem()
 
-	rnd := rand.New(rand.NewSource(time.Now().Unix()))
 	typ := v.Type()
 	for i := 0; i < typ.NumField(); i++ {
 		f := v.Field(i)
@@ -581,40 +618,49 @@
 			continue
 		}
 
-		// testing/quick can't handle functions or interfaces.
-		fn := typ.Field(i).Name
-		switch fn {
+		// testing/quick can't handle functions or interfaces and so
+		// isn't used here.
+		switch fn := typ.Field(i).Name; fn {
 		case "Rand":
 			f.Set(reflect.ValueOf(io.Reader(os.Stdin)))
-			continue
 		case "Time", "GetCertificate", "GetConfigForClient", "VerifyPeerCertificate", "GetClientCertificate":
-			// DeepEqual can't compare functions.
-			continue
+			// DeepEqual can't compare functions. If you add a
+			// function field to this list, you must also change
+			// TestCloneFuncFields to ensure that the func field is
+			// cloned.
 		case "Certificates":
 			f.Set(reflect.ValueOf([]Certificate{
 				{Certificate: [][]byte{{'b'}}},
 			}))
-			continue
 		case "NameToCertificate":
 			f.Set(reflect.ValueOf(map[string]*Certificate{"a": nil}))
-			continue
 		case "RootCAs", "ClientCAs":
 			f.Set(reflect.ValueOf(x509.NewCertPool()))
-			continue
 		case "ClientSessionCache":
 			f.Set(reflect.ValueOf(NewLRUClientSessionCache(10)))
-			continue
 		case "KeyLogWriter":
 			f.Set(reflect.ValueOf(io.Writer(os.Stdout)))
-			continue
-
+		case "NextProtos":
+			f.Set(reflect.ValueOf([]string{"a", "b"}))
+		case "ServerName":
+			f.Set(reflect.ValueOf("b"))
+		case "ClientAuth":
+			f.Set(reflect.ValueOf(VerifyClientCertIfGiven))
+		case "InsecureSkipVerify", "SessionTicketsDisabled", "DynamicRecordSizingDisabled", "PreferServerCipherSuites":
+			f.Set(reflect.ValueOf(true))
+		case "MinVersion", "MaxVersion":
+			f.Set(reflect.ValueOf(uint16(VersionTLS12)))
+		case "SessionTicketKey":
+			f.Set(reflect.ValueOf([32]byte{}))
+		case "CipherSuites":
+			f.Set(reflect.ValueOf([]uint16{1, 2}))
+		case "CurvePreferences":
+			f.Set(reflect.ValueOf([]CurveID{CurveP256}))
+		case "Renegotiation":
+			f.Set(reflect.ValueOf(RenegotiateOnceAsClient))
+		default:
+			t.Errorf("all fields must be accounted for, but saw unknown field %q", fn)
 		}
-
-		q, ok := quick.Value(f.Type(), rnd)
-		if !ok {
-			t.Fatalf("quick.Value failed on field %s", fn)
-		}
-		f.Set(q)
 	}
 
 	c2 := c1.Clone()
diff --git a/src/crypto/x509/root_linux.go b/src/crypto/x509/root_linux.go
index 38dd72d..aa1785e 100644
--- a/src/crypto/x509/root_linux.go
+++ b/src/crypto/x509/root_linux.go
@@ -7,8 +7,8 @@
 // Possible certificate files; stop after finding one.
 var certFiles = []string{
 	"/etc/ssl/certs/ca-certificates.crt",                // Debian/Ubuntu/Gentoo etc.
-	"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
 	"/etc/pki/tls/certs/ca-bundle.crt",                  // Fedora/RHEL 6
 	"/etc/ssl/ca-bundle.pem",                            // OpenSUSE
 	"/etc/pki/tls/cacert.pem",                           // OpenELEC
+	"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
 }
diff --git a/src/database/sql/ctxutil.go b/src/database/sql/ctxutil.go
index 1071446..bd652b5 100644
--- a/src/database/sql/ctxutil.go
+++ b/src/database/sql/ctxutil.go
@@ -35,15 +35,12 @@
 		return nil, err
 	}
 
-	resi, err := execer.Exec(query, dargs)
-	if err == nil {
-		select {
-		default:
-		case <-ctx.Done():
-			return resi, ctx.Err()
-		}
+	select {
+	default:
+	case <-ctx.Done():
+		return nil, ctx.Err()
 	}
-	return resi, err
+	return execer.Exec(query, dargs)
 }
 
 func ctxDriverQuery(ctx context.Context, queryer driver.Queryer, query string, nvdargs []driver.NamedValue) (driver.Rows, error) {
@@ -56,16 +53,12 @@
 		return nil, err
 	}
 
-	rowsi, err := queryer.Query(query, dargs)
-	if err == nil {
-		select {
-		default:
-		case <-ctx.Done():
-			rowsi.Close()
-			return nil, ctx.Err()
-		}
+	select {
+	default:
+	case <-ctx.Done():
+		return nil, ctx.Err()
 	}
-	return rowsi, err
+	return queryer.Query(query, dargs)
 }
 
 func ctxDriverStmtExec(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Result, error) {
@@ -77,15 +70,12 @@
 		return nil, err
 	}
 
-	resi, err := si.Exec(dargs)
-	if err == nil {
-		select {
-		default:
-		case <-ctx.Done():
-			return resi, ctx.Err()
-		}
+	select {
+	default:
+	case <-ctx.Done():
+		return nil, ctx.Err()
 	}
-	return resi, err
+	return si.Exec(dargs)
 }
 
 func ctxDriverStmtQuery(ctx context.Context, si driver.Stmt, nvdargs []driver.NamedValue) (driver.Rows, error) {
@@ -97,16 +87,12 @@
 		return nil, err
 	}
 
-	rowsi, err := si.Query(dargs)
-	if err == nil {
-		select {
-		default:
-		case <-ctx.Done():
-			rowsi.Close()
-			return nil, ctx.Err()
-		}
+	select {
+	default:
+	case <-ctx.Done():
+		return nil, ctx.Err()
 	}
-	return rowsi, err
+	return si.Query(dargs)
 }
 
 var errLevelNotSupported = errors.New("sql: selected isolation level is not supported")
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index feb9122..c016681 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -305,8 +305,9 @@
 
 	mu           sync.Mutex // protects following fields
 	freeConn     []*driverConn
-	connRequests []chan connRequest
-	numOpen      int // number of opened and pending open connections
+	connRequests map[uint64]chan connRequest
+	nextRequest  uint64 // Next key to use in connRequests.
+	numOpen      int    // number of opened and pending open connections
 	// Used to signal the need for new connections
 	// a goroutine running connectionOpener() reads on this chan and
 	// maybeOpenNewConnections sends on the chan (one send per needed connection)
@@ -572,10 +573,11 @@
 		return nil, fmt.Errorf("sql: unknown driver %q (forgotten import?)", driverName)
 	}
 	db := &DB{
-		driver:   driveri,
-		dsn:      dataSourceName,
-		openerCh: make(chan struct{}, connectionRequestQueueSize),
-		lastPut:  make(map[*driverConn]string),
+		driver:       driveri,
+		dsn:          dataSourceName,
+		openerCh:     make(chan struct{}, connectionRequestQueueSize),
+		lastPut:      make(map[*driverConn]string),
+		connRequests: make(map[uint64]chan connRequest),
 	}
 	go db.connectionOpener()
 	return db, nil
@@ -881,6 +883,14 @@
 
 var errDBClosed = errors.New("sql: database is closed")
 
+// nextRequestKeyLocked returns the next connection request key.
+// It is assumed that nextRequest will not overflow.
+func (db *DB) nextRequestKeyLocked() uint64 {
+	next := db.nextRequest
+	db.nextRequest++
+	return next
+}
+
 // conn returns a newly-opened or cached *driverConn.
 func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn, error) {
 	db.mu.Lock()
@@ -918,12 +928,25 @@
 		// Make the connRequest channel. It's buffered so that the
 		// connectionOpener doesn't block while waiting for the req to be read.
 		req := make(chan connRequest, 1)
-		db.connRequests = append(db.connRequests, req)
+		reqKey := db.nextRequestKeyLocked()
+		db.connRequests[reqKey] = req
 		db.mu.Unlock()
 
 		// Timeout the connection request with the context.
 		select {
 		case <-ctx.Done():
+			// Remove the connection request and ensure no value has been sent
+			// on it after removing.
+			db.mu.Lock()
+			delete(db.connRequests, reqKey)
+			db.mu.Unlock()
+			select {
+			default:
+			case ret, ok := <-req:
+				if ok {
+					db.putConn(ret.conn, ret.err)
+				}
+			}
 			return nil, ctx.Err()
 		case ret, ok := <-req:
 			if !ok {
@@ -1044,12 +1067,12 @@
 		return false
 	}
 	if c := len(db.connRequests); c > 0 {
-		req := db.connRequests[0]
-		// This copy is O(n) but in practice faster than a linked list.
-		// TODO: consider compacting it down less often and
-		// moving the base instead?
-		copy(db.connRequests, db.connRequests[1:])
-		db.connRequests = db.connRequests[:c-1]
+		var req chan connRequest
+		var reqKey uint64
+		for reqKey, req = range db.connRequests {
+			break
+		}
+		delete(db.connRequests, reqKey) // Remove from pending requests.
 		if err == nil {
 			dc.inUse = true
 		}
@@ -2071,14 +2094,21 @@
 	dc          *driverConn // owned; must call releaseConn when closed to release
 	releaseConn func(error)
 	rowsi       driver.Rows
+	cancel      func()      // called when Rows is closed, may be nil.
+	closeStmt   *driverStmt // if non-nil, statement to Close on close
 
-	// closed value is 1 when the Rows is closed.
-	// Use atomic operations on value when checking value.
-	closed    int32
-	cancel    func() // called when Rows is closed, may be nil.
-	lastcols  []driver.Value
-	lasterr   error       // non-nil only if closed is true
-	closeStmt *driverStmt // if non-nil, statement to Close on close
+	// closemu prevents Rows from closing while there
+	// is an active streaming result. It is held for read during non-close operations
+	// and exclusively during close.
+	//
+	// closemu guards lasterr and closed.
+	closemu sync.RWMutex
+	closed  bool
+	lasterr error // non-nil only if closed is true
+
+	// lastcols is only used in Scan, Next, and NextResultSet which are expected
+	// not not be called concurrently.
+	lastcols []driver.Value
 }
 
 func (rs *Rows) initContextClose(ctx context.Context) {
@@ -2089,7 +2119,7 @@
 // awaitDone blocks until the rows are closed or the context canceled.
 func (rs *Rows) awaitDone(ctx context.Context) {
 	<-ctx.Done()
-	rs.Close()
+	rs.close(ctx.Err())
 }
 
 // Next prepares the next result row for reading with the Scan method. It
@@ -2099,8 +2129,19 @@
 //
 // Every call to Scan, even the first one, must be preceded by a call to Next.
 func (rs *Rows) Next() bool {
-	if rs.isClosed() {
-		return false
+	var doClose, ok bool
+	withLock(rs.closemu.RLocker(), func() {
+		doClose, ok = rs.nextLocked()
+	})
+	if doClose {
+		rs.Close()
+	}
+	return ok
+}
+
+func (rs *Rows) nextLocked() (doClose, ok bool) {
+	if rs.closed {
+		return false, false
 	}
 	if rs.lastcols == nil {
 		rs.lastcols = make([]driver.Value, len(rs.rowsi.Columns()))
@@ -2109,23 +2150,21 @@
 	if rs.lasterr != nil {
 		// Close the connection if there is a driver error.
 		if rs.lasterr != io.EOF {
-			rs.Close()
-			return false
+			return true, false
 		}
 		nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
 		if !ok {
-			rs.Close()
-			return false
+			return true, false
 		}
 		// The driver is at the end of the current result set.
 		// Test to see if there is another result set after the current one.
 		// Only close Rows if there is no further result sets to read.
 		if !nextResultSet.HasNextResultSet() {
-			rs.Close()
+			doClose = true
 		}
-		return false
+		return doClose, false
 	}
-	return true
+	return false, true
 }
 
 // NextResultSet prepares the next result set for reading. It returns true if
@@ -2137,18 +2176,28 @@
 // scanning. If there are further result sets they may not have rows in the result
 // set.
 func (rs *Rows) NextResultSet() bool {
-	if rs.isClosed() {
+	var doClose bool
+	defer func() {
+		if doClose {
+			rs.Close()
+		}
+	}()
+	rs.closemu.RLock()
+	defer rs.closemu.RUnlock()
+
+	if rs.closed {
 		return false
 	}
+
 	rs.lastcols = nil
 	nextResultSet, ok := rs.rowsi.(driver.RowsNextResultSet)
 	if !ok {
-		rs.Close()
+		doClose = true
 		return false
 	}
 	rs.lasterr = nextResultSet.NextResultSet()
 	if rs.lasterr != nil {
-		rs.Close()
+		doClose = true
 		return false
 	}
 	return true
@@ -2157,6 +2206,8 @@
 // Err returns the error, if any, that was encountered during iteration.
 // Err may be called after an explicit or implicit Close.
 func (rs *Rows) Err() error {
+	rs.closemu.RLock()
+	defer rs.closemu.RUnlock()
 	if rs.lasterr == io.EOF {
 		return nil
 	}
@@ -2167,7 +2218,9 @@
 // Columns returns an error if the rows are closed, or if the rows
 // are from QueryRow and there was a deferred error.
 func (rs *Rows) Columns() ([]string, error) {
-	if rs.isClosed() {
+	rs.closemu.RLock()
+	defer rs.closemu.RUnlock()
+	if rs.closed {
 		return nil, errors.New("sql: Rows are closed")
 	}
 	if rs.rowsi == nil {
@@ -2179,7 +2232,9 @@
 // ColumnTypes returns column information such as column type, length,
 // and nullable. Some information may not be available from some drivers.
 func (rs *Rows) ColumnTypes() ([]*ColumnType, error) {
-	if rs.isClosed() {
+	rs.closemu.RLock()
+	defer rs.closemu.RUnlock()
+	if rs.closed {
 		return nil, errors.New("sql: Rows are closed")
 	}
 	if rs.rowsi == nil {
@@ -2329,9 +2384,13 @@
 // For scanning into *bool, the source may be true, false, 1, 0, or
 // string inputs parseable by strconv.ParseBool.
 func (rs *Rows) Scan(dest ...interface{}) error {
-	if rs.isClosed() {
+	rs.closemu.RLock()
+	if rs.closed {
+		rs.closemu.RUnlock()
 		return errors.New("sql: Rows are closed")
 	}
+	rs.closemu.RUnlock()
+
 	if rs.lastcols == nil {
 		return errors.New("sql: Scan called without calling Next")
 	}
@@ -2351,20 +2410,28 @@
 // hook throug a test only mutex.
 var rowsCloseHook = func() func(*Rows, *error) { return nil }
 
-func (rs *Rows) isClosed() bool {
-	return atomic.LoadInt32(&rs.closed) != 0
-}
-
 // Close closes the Rows, preventing further enumeration. If Next is called
 // and returns false and there are no further result sets,
 // the Rows are closed automatically and it will suffice to check the
 // result of Err. Close is idempotent and does not affect the result of Err.
 func (rs *Rows) Close() error {
-	if !atomic.CompareAndSwapInt32(&rs.closed, 0, 1) {
+	return rs.close(nil)
+}
+
+func (rs *Rows) close(err error) error {
+	rs.closemu.Lock()
+	defer rs.closemu.Unlock()
+
+	if rs.closed {
 		return nil
 	}
+	rs.closed = true
 
-	err := rs.rowsi.Close()
+	if rs.lasterr == nil {
+		rs.lasterr = err
+	}
+
+	err = rs.rowsi.Close()
 	if fn := rowsCloseHook(); fn != nil {
 		fn(rs, &err)
 	}
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 898df3b..450e5f1 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -153,8 +153,13 @@
 	if err != nil {
 		t.Fatalf("error closing DB: %v", err)
 	}
-	if count := db.numOpenConns(); count != 0 {
-		t.Fatalf("%d connections still open after closing DB", count)
+
+	var numOpen int
+	if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
+		numOpen = db.numOpenConns()
+		return numOpen == 0
+	}) {
+		t.Fatalf("%d connections still open after closing DB", numOpen)
 	}
 }
 
@@ -276,6 +281,7 @@
 	}
 }
 
+// TestQueryContext tests canceling the context while scanning the rows.
 func TestQueryContext(t *testing.T) {
 	db := newTestDB(t, "people")
 	defer closeDB(t, db)
@@ -297,7 +303,7 @@
 	for rows.Next() {
 		if index == 2 {
 			cancel()
-			time.Sleep(10 * time.Millisecond)
+			waitForRowsClose(t, rows, 5*time.Second)
 		}
 		var r row
 		err = rows.Scan(&r.age, &r.name)
@@ -313,9 +319,13 @@
 		got = append(got, r)
 		index++
 	}
-	err = rows.Err()
-	if err != nil {
-		t.Fatalf("Err: %v", err)
+	select {
+	case <-ctx.Done():
+		if err := ctx.Err(); err != context.Canceled {
+			t.Fatalf("context err = %v; want context.Canceled")
+		}
+	default:
+		t.Fatalf("context err = nil; want context.Canceled")
 	}
 	want := []row{
 		{age: 1, name: "Alice"},
@@ -327,6 +337,7 @@
 
 	// And verify that the final rows.Next() call, which hit EOF,
 	// also closed the rows connection.
+	waitForRowsClose(t, rows, 5*time.Second)
 	waitForFree(t, db, 5*time.Second, 1)
 	if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
 		t.Errorf("executed %d Prepare statements; want 1", prepares)
@@ -356,12 +367,27 @@
 	}
 }
 
+func waitForRowsClose(t *testing.T, rows *Rows, maxWait time.Duration) {
+	if !waitCondition(maxWait, 5*time.Millisecond, func() bool {
+		rows.closemu.RLock()
+		defer rows.closemu.RUnlock()
+		return rows.closed
+	}) {
+		t.Fatal("failed to close rows")
+	}
+}
+
+// TestQueryContextWait ensures that rows and all internal statements are closed when
+// a query context is closed during execution.
 func TestQueryContextWait(t *testing.T) {
 	db := newTestDB(t, "people")
 	defer closeDB(t, db)
 	prepares0 := numPrepares(t, db)
 
-	ctx, _ := context.WithTimeout(context.Background(), time.Millisecond*15)
+	// TODO(kardianos): convert this from using a timeout to using an explicit
+	// cancel when the query signals that is is "executing" the query.
+	ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond)
+	defer cancel()
 
 	// This will trigger the *fakeConn.Prepare method which will take time
 	// performing the query. The ctxDriverPrepare func will check the context
@@ -374,10 +400,15 @@
 	// Verify closed rows connection after error condition.
 	waitForFree(t, db, 5*time.Second, 1)
 	if prepares := numPrepares(t, db) - prepares0; prepares != 1 {
-		t.Errorf("executed %d Prepare statements; want 1", prepares)
+		// TODO(kardianos): if the context timeouts before the db.QueryContext
+		// executes this check may fail. After adjusting how the context
+		// is canceled above revert this back to a Fatal error.
+		t.Logf("executed %d Prepare statements; want 1", prepares)
 	}
 }
 
+// TestTxContextWait tests the transaction behavior when the tx context is canceled
+// during execution of the query.
 func TestTxContextWait(t *testing.T) {
 	db := newTestDB(t, "people")
 	defer closeDB(t, db)
@@ -386,6 +417,10 @@
 
 	tx, err := db.BeginTx(ctx, nil)
 	if err != nil {
+		// Guard against the context being canceled before BeginTx completes.
+		if err == context.DeadlineExceeded {
+			t.Skip("tx context canceled prior to first use")
+		}
 		t.Fatal(err)
 	}
 
@@ -398,12 +433,6 @@
 	}
 
 	waitForFree(t, db, 5*time.Second, 0)
-
-	// Ensure the dropped connection allows more connections to be made.
-	// Checked on DB Close.
-	waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
-		return db.numOpenConns() == 0
-	})
 }
 
 func TestMultiResultSetQuery(t *testing.T) {
@@ -527,6 +556,63 @@
 	}
 }
 
+func TestPoolExhaustOnCancel(t *testing.T) {
+	if testing.Short() {
+		t.Skip("long test")
+	}
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	max := 3
+
+	db.SetMaxOpenConns(max)
+
+	// First saturate the connection pool.
+	// Then start new requests for a connection that is cancelled after it is requested.
+
+	var saturate, saturateDone sync.WaitGroup
+	saturate.Add(max)
+	saturateDone.Add(max)
+
+	for i := 0; i < max; i++ {
+		go func() {
+			saturate.Done()
+			rows, err := db.Query("WAIT|500ms|SELECT|people|name,photo|")
+			if err != nil {
+				t.Fatalf("Query: %v", err)
+			}
+			rows.Close()
+			saturateDone.Done()
+		}()
+	}
+
+	saturate.Wait()
+
+	// Now cancel the request while it is waiting.
+	ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
+	defer cancel()
+
+	for i := 0; i < max; i++ {
+		ctxReq, cancelReq := context.WithCancel(ctx)
+		go func() {
+			time.Sleep(time.Millisecond * 100)
+			cancelReq()
+		}()
+		err := db.PingContext(ctxReq)
+		if err != context.Canceled {
+			t.Fatalf("PingContext (Exhaust): %v", err)
+		}
+	}
+
+	saturateDone.Wait()
+
+	// Now try to open a normal connection.
+	err := db.PingContext(ctx)
+	if err != nil {
+		t.Fatalf("PingContext (Normal): %v", err)
+	}
+}
+
 func TestByteOwnership(t *testing.T) {
 	db := newTestDB(t, "people")
 	defer closeDB(t, db)
@@ -2677,7 +2763,6 @@
 		}()
 	}
 	wg.Wait()
-	time.Sleep(milliWait * 3 * time.Millisecond)
 }
 
 // TestIssue18719 closes the context right before use. The sql.driverConn
@@ -2720,14 +2805,8 @@
 	// Do not explicitly rollback. The rollback will happen from the
 	// canceled context.
 
-	// Wait for connections to return to pool.
-	var numOpen int
-	if !waitCondition(5*time.Second, 5*time.Millisecond, func() bool {
-		numOpen = db.numOpenConns()
-		return numOpen == 0
-	}) {
-		t.Fatalf("open conns after hitting EOF = %d; want 0", numOpen)
-	}
+	cancel()
+	waitForRowsClose(t, rows, 5*time.Second)
 }
 
 func TestConcurrency(t *testing.T) {
diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go
index 1176f5d..4c6ba8c 100644
--- a/src/encoding/xml/marshal.go
+++ b/src/encoding/xml/marshal.go
@@ -775,6 +775,20 @@
 
 var ddBytes = []byte("--")
 
+// indirect drills into interfaces and pointers, returning the pointed-at value.
+// If it encounters a nil interface or pointer, indirect returns that nil value.
+// This can turn into an infinite loop given a cyclic chain,
+// but it matches the Go 1 behavior.
+func indirect(vf reflect.Value) reflect.Value {
+	for vf.Kind() == reflect.Interface || vf.Kind() == reflect.Ptr {
+		if vf.IsNil() {
+			return vf
+		}
+		vf = vf.Elem()
+	}
+	return vf
+}
+
 func (p *printer) marshalStruct(tinfo *typeInfo, val reflect.Value) error {
 	s := parentStack{p: p}
 	for i := range tinfo.fields {
@@ -816,17 +830,9 @@
 					continue
 				}
 			}
-			// Drill into interfaces and pointers.
-			// This can turn into an infinite loop given a cyclic chain,
-			// but it matches the Go 1 behavior.
-			for vf.Kind() == reflect.Interface || vf.Kind() == reflect.Ptr {
-				if vf.IsNil() {
-					return nil
-				}
-				vf = vf.Elem()
-			}
 
 			var scratch [64]byte
+			vf = indirect(vf)
 			switch vf.Kind() {
 			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
 				if err := emit(p, strconv.AppendInt(scratch[:0], vf.Int(), 10)); err != nil {
@@ -861,6 +867,7 @@
 			if err := s.trim(finfo.parents); err != nil {
 				return err
 			}
+			vf = indirect(vf)
 			k := vf.Kind()
 			if !(k == reflect.String || k == reflect.Slice && vf.Type().Elem().Kind() == reflect.Uint8) {
 				return fmt.Errorf("xml: bad type for comment field of %s", val.Type())
@@ -901,6 +908,7 @@
 			continue
 
 		case fInnerXml:
+			vf = indirect(vf)
 			iface := vf.Interface()
 			switch raw := iface.(type) {
 			case []byte:
diff --git a/src/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go
index d79b99a..0126146 100644
--- a/src/encoding/xml/marshal_test.go
+++ b/src/encoding/xml/marshal_test.go
@@ -386,6 +386,140 @@
 	return &x
 }
 
+func stringptr(x string) *string {
+	return &x
+}
+
+type T1 struct{}
+type T2 struct{}
+type T3 struct{}
+
+type IndirComment struct {
+	T1      T1
+	Comment *string `xml:",comment"`
+	T2      T2
+}
+
+type DirectComment struct {
+	T1      T1
+	Comment string `xml:",comment"`
+	T2      T2
+}
+
+type IfaceComment struct {
+	T1      T1
+	Comment interface{} `xml:",comment"`
+	T2      T2
+}
+
+type IndirChardata struct {
+	T1       T1
+	Chardata *string `xml:",chardata"`
+	T2       T2
+}
+
+type DirectChardata struct {
+	T1       T1
+	Chardata string `xml:",chardata"`
+	T2       T2
+}
+
+type IfaceChardata struct {
+	T1       T1
+	Chardata interface{} `xml:",chardata"`
+	T2       T2
+}
+
+type IndirCDATA struct {
+	T1    T1
+	CDATA *string `xml:",cdata"`
+	T2    T2
+}
+
+type DirectCDATA struct {
+	T1    T1
+	CDATA string `xml:",cdata"`
+	T2    T2
+}
+
+type IfaceCDATA struct {
+	T1    T1
+	CDATA interface{} `xml:",cdata"`
+	T2    T2
+}
+
+type IndirInnerXML struct {
+	T1       T1
+	InnerXML *string `xml:",innerxml"`
+	T2       T2
+}
+
+type DirectInnerXML struct {
+	T1       T1
+	InnerXML string `xml:",innerxml"`
+	T2       T2
+}
+
+type IfaceInnerXML struct {
+	T1       T1
+	InnerXML interface{} `xml:",innerxml"`
+	T2       T2
+}
+
+type IndirElement struct {
+	T1      T1
+	Element *string
+	T2      T2
+}
+
+type DirectElement struct {
+	T1      T1
+	Element string
+	T2      T2
+}
+
+type IfaceElement struct {
+	T1      T1
+	Element interface{}
+	T2      T2
+}
+
+type IndirOmitEmpty struct {
+	T1        T1
+	OmitEmpty *string `xml:",omitempty"`
+	T2        T2
+}
+
+type DirectOmitEmpty struct {
+	T1        T1
+	OmitEmpty string `xml:",omitempty"`
+	T2        T2
+}
+
+type IfaceOmitEmpty struct {
+	T1        T1
+	OmitEmpty interface{} `xml:",omitempty"`
+	T2        T2
+}
+
+type IndirAny struct {
+	T1  T1
+	Any *string `xml:",any"`
+	T2  T2
+}
+
+type DirectAny struct {
+	T1  T1
+	Any string `xml:",any"`
+	T2  T2
+}
+
+type IfaceAny struct {
+	T1  T1
+	Any interface{} `xml:",any"`
+	T2  T2
+}
+
 var (
 	nameAttr     = "Sarah"
 	ageAttr      = uint(12)
@@ -398,10 +532,12 @@
 // please try to make them two-way as well to ensure that
 // marshaling and unmarshaling are as symmetrical as feasible.
 var marshalTests = []struct {
-	Value         interface{}
-	ExpectXML     string
-	MarshalOnly   bool
-	UnmarshalOnly bool
+	Value          interface{}
+	ExpectXML      string
+	MarshalOnly    bool
+	MarshalError   string
+	UnmarshalOnly  bool
+	UnmarshalError string
 }{
 	// Test nil marshals to nothing
 	{Value: nil, ExpectXML: ``, MarshalOnly: true},
@@ -1133,6 +1269,382 @@
 		ExpectXML: `<NestedAndCData><A><B></B><B></B></A><![CDATA[test]]></NestedAndCData>`,
 		Value:     &NestedAndCData{AB: make([]string, 2), CDATA: "test"},
 	},
+	// Test pointer indirection in various kinds of fields.
+	// https://golang.org/issue/19063
+	{
+		ExpectXML:   `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`,
+		Value:       &IndirComment{Comment: stringptr("hi")},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:   `<IndirComment><T1></T1><T2></T2></IndirComment>`,
+		Value:       &IndirComment{Comment: stringptr("")},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:    `<IndirComment><T1></T1><T2></T2></IndirComment>`,
+		Value:        &IndirComment{Comment: nil},
+		MarshalError: "xml: bad type for comment field of xml.IndirComment",
+	},
+	{
+		ExpectXML:     `<IndirComment><T1></T1><!--hi--><T2></T2></IndirComment>`,
+		Value:         &IndirComment{Comment: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:   `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`,
+		Value:       &IfaceComment{Comment: "hi"},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IfaceComment><T1></T1><!--hi--><T2></T2></IfaceComment>`,
+		Value:         &IfaceComment{Comment: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:    `<IfaceComment><T1></T1><T2></T2></IfaceComment>`,
+		Value:        &IfaceComment{Comment: nil},
+		MarshalError: "xml: bad type for comment field of xml.IfaceComment",
+	},
+	{
+		ExpectXML:     `<IfaceComment><T1></T1><T2></T2></IfaceComment>`,
+		Value:         &IfaceComment{Comment: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<DirectComment><T1></T1><!--hi--><T2></T2></DirectComment>`,
+		Value:     &DirectComment{Comment: string("hi")},
+	},
+	{
+		ExpectXML: `<DirectComment><T1></T1><T2></T2></DirectComment>`,
+		Value:     &DirectComment{Comment: string("")},
+	},
+	{
+		ExpectXML: `<IndirChardata><T1></T1>hi<T2></T2></IndirChardata>`,
+		Value:     &IndirChardata{Chardata: stringptr("hi")},
+	},
+	{
+		ExpectXML:     `<IndirChardata><T1></T1><![CDATA[hi]]><T2></T2></IndirChardata>`,
+		Value:         &IndirChardata{Chardata: stringptr("hi")},
+		UnmarshalOnly: true, // marshals without CDATA
+	},
+	{
+		ExpectXML: `<IndirChardata><T1></T1><T2></T2></IndirChardata>`,
+		Value:     &IndirChardata{Chardata: stringptr("")},
+	},
+	{
+		ExpectXML:   `<IndirChardata><T1></T1><T2></T2></IndirChardata>`,
+		Value:       &IndirChardata{Chardata: nil},
+		MarshalOnly: true, // unmarshal leaves Chardata=stringptr("")
+	},
+	{
+		ExpectXML:      `<IfaceChardata><T1></T1>hi<T2></T2></IfaceChardata>`,
+		Value:          &IfaceChardata{Chardata: string("hi")},
+		UnmarshalError: "cannot unmarshal into interface {}",
+	},
+	{
+		ExpectXML:      `<IfaceChardata><T1></T1><![CDATA[hi]]><T2></T2></IfaceChardata>`,
+		Value:          &IfaceChardata{Chardata: string("hi")},
+		UnmarshalOnly:  true, // marshals without CDATA
+		UnmarshalError: "cannot unmarshal into interface {}",
+	},
+	{
+		ExpectXML:      `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`,
+		Value:          &IfaceChardata{Chardata: string("")},
+		UnmarshalError: "cannot unmarshal into interface {}",
+	},
+	{
+		ExpectXML:      `<IfaceChardata><T1></T1><T2></T2></IfaceChardata>`,
+		Value:          &IfaceChardata{Chardata: nil},
+		UnmarshalError: "cannot unmarshal into interface {}",
+	},
+	{
+		ExpectXML: `<DirectChardata><T1></T1>hi<T2></T2></DirectChardata>`,
+		Value:     &DirectChardata{Chardata: string("hi")},
+	},
+	{
+		ExpectXML:     `<DirectChardata><T1></T1><![CDATA[hi]]><T2></T2></DirectChardata>`,
+		Value:         &DirectChardata{Chardata: string("hi")},
+		UnmarshalOnly: true, // marshals without CDATA
+	},
+	{
+		ExpectXML: `<DirectChardata><T1></T1><T2></T2></DirectChardata>`,
+		Value:     &DirectChardata{Chardata: string("")},
+	},
+	{
+		ExpectXML: `<IndirCDATA><T1></T1><![CDATA[hi]]><T2></T2></IndirCDATA>`,
+		Value:     &IndirCDATA{CDATA: stringptr("hi")},
+	},
+	{
+		ExpectXML:     `<IndirCDATA><T1></T1>hi<T2></T2></IndirCDATA>`,
+		Value:         &IndirCDATA{CDATA: stringptr("hi")},
+		UnmarshalOnly: true, // marshals with CDATA
+	},
+	{
+		ExpectXML: `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`,
+		Value:     &IndirCDATA{CDATA: stringptr("")},
+	},
+	{
+		ExpectXML:   `<IndirCDATA><T1></T1><T2></T2></IndirCDATA>`,
+		Value:       &IndirCDATA{CDATA: nil},
+		MarshalOnly: true, // unmarshal leaves CDATA=stringptr("")
+	},
+	{
+		ExpectXML:      `<IfaceCDATA><T1></T1><![CDATA[hi]]><T2></T2></IfaceCDATA>`,
+		Value:          &IfaceCDATA{CDATA: string("hi")},
+		UnmarshalError: "cannot unmarshal into interface {}",
+	},
+	{
+		ExpectXML:      `<IfaceCDATA><T1></T1>hi<T2></T2></IfaceCDATA>`,
+		Value:          &IfaceCDATA{CDATA: string("hi")},
+		UnmarshalOnly:  true, // marshals with CDATA
+		UnmarshalError: "cannot unmarshal into interface {}",
+	},
+	{
+		ExpectXML:      `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`,
+		Value:          &IfaceCDATA{CDATA: string("")},
+		UnmarshalError: "cannot unmarshal into interface {}",
+	},
+	{
+		ExpectXML:      `<IfaceCDATA><T1></T1><T2></T2></IfaceCDATA>`,
+		Value:          &IfaceCDATA{CDATA: nil},
+		UnmarshalError: "cannot unmarshal into interface {}",
+	},
+	{
+		ExpectXML: `<DirectCDATA><T1></T1><![CDATA[hi]]><T2></T2></DirectCDATA>`,
+		Value:     &DirectCDATA{CDATA: string("hi")},
+	},
+	{
+		ExpectXML:     `<DirectCDATA><T1></T1>hi<T2></T2></DirectCDATA>`,
+		Value:         &DirectCDATA{CDATA: string("hi")},
+		UnmarshalOnly: true, // marshals with CDATA
+	},
+	{
+		ExpectXML: `<DirectCDATA><T1></T1><T2></T2></DirectCDATA>`,
+		Value:     &DirectCDATA{CDATA: string("")},
+	},
+	{
+		ExpectXML:   `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`,
+		Value:       &IndirInnerXML{InnerXML: stringptr("<hi/>")},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:   `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`,
+		Value:       &IndirInnerXML{InnerXML: stringptr("")},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML: `<IndirInnerXML><T1></T1><T2></T2></IndirInnerXML>`,
+		Value:     &IndirInnerXML{InnerXML: nil},
+	},
+	{
+		ExpectXML:     `<IndirInnerXML><T1></T1><hi/><T2></T2></IndirInnerXML>`,
+		Value:         &IndirInnerXML{InnerXML: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:   `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`,
+		Value:       &IfaceInnerXML{InnerXML: "<hi/>"},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IfaceInnerXML><T1></T1><hi/><T2></T2></IfaceInnerXML>`,
+		Value:         &IfaceInnerXML{InnerXML: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`,
+		Value:     &IfaceInnerXML{InnerXML: nil},
+	},
+	{
+		ExpectXML:     `<IfaceInnerXML><T1></T1><T2></T2></IfaceInnerXML>`,
+		Value:         &IfaceInnerXML{InnerXML: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:   `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`,
+		Value:       &DirectInnerXML{InnerXML: string("<hi/>")},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<DirectInnerXML><T1></T1><hi/><T2></T2></DirectInnerXML>`,
+		Value:         &DirectInnerXML{InnerXML: string("<T1></T1><hi/><T2></T2>")},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:   `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`,
+		Value:       &DirectInnerXML{InnerXML: string("")},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<DirectInnerXML><T1></T1><T2></T2></DirectInnerXML>`,
+		Value:         &DirectInnerXML{InnerXML: string("<T1></T1><T2></T2>")},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<IndirElement><T1></T1><Element>hi</Element><T2></T2></IndirElement>`,
+		Value:     &IndirElement{Element: stringptr("hi")},
+	},
+	{
+		ExpectXML: `<IndirElement><T1></T1><Element></Element><T2></T2></IndirElement>`,
+		Value:     &IndirElement{Element: stringptr("")},
+	},
+	{
+		ExpectXML: `<IndirElement><T1></T1><T2></T2></IndirElement>`,
+		Value:     &IndirElement{Element: nil},
+	},
+	{
+		ExpectXML:   `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`,
+		Value:       &IfaceElement{Element: "hi"},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IfaceElement><T1></T1><Element>hi</Element><T2></T2></IfaceElement>`,
+		Value:         &IfaceElement{Element: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<IfaceElement><T1></T1><T2></T2></IfaceElement>`,
+		Value:     &IfaceElement{Element: nil},
+	},
+	{
+		ExpectXML:     `<IfaceElement><T1></T1><T2></T2></IfaceElement>`,
+		Value:         &IfaceElement{Element: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<DirectElement><T1></T1><Element>hi</Element><T2></T2></DirectElement>`,
+		Value:     &DirectElement{Element: string("hi")},
+	},
+	{
+		ExpectXML: `<DirectElement><T1></T1><Element></Element><T2></T2></DirectElement>`,
+		Value:     &DirectElement{Element: string("")},
+	},
+	{
+		ExpectXML: `<IndirOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IndirOmitEmpty>`,
+		Value:     &IndirOmitEmpty{OmitEmpty: stringptr("hi")},
+	},
+	{
+		// Note: Changed in Go 1.8 to include <OmitEmpty> element (because x.OmitEmpty != nil).
+		ExpectXML:   `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`,
+		Value:       &IndirOmitEmpty{OmitEmpty: stringptr("")},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IndirOmitEmpty><T1></T1><OmitEmpty></OmitEmpty><T2></T2></IndirOmitEmpty>`,
+		Value:         &IndirOmitEmpty{OmitEmpty: stringptr("")},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<IndirOmitEmpty><T1></T1><T2></T2></IndirOmitEmpty>`,
+		Value:     &IndirOmitEmpty{OmitEmpty: nil},
+	},
+	{
+		ExpectXML:   `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`,
+		Value:       &IfaceOmitEmpty{OmitEmpty: "hi"},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IfaceOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></IfaceOmitEmpty>`,
+		Value:         &IfaceOmitEmpty{OmitEmpty: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`,
+		Value:     &IfaceOmitEmpty{OmitEmpty: nil},
+	},
+	{
+		ExpectXML:     `<IfaceOmitEmpty><T1></T1><T2></T2></IfaceOmitEmpty>`,
+		Value:         &IfaceOmitEmpty{OmitEmpty: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<DirectOmitEmpty><T1></T1><OmitEmpty>hi</OmitEmpty><T2></T2></DirectOmitEmpty>`,
+		Value:     &DirectOmitEmpty{OmitEmpty: string("hi")},
+	},
+	{
+		ExpectXML: `<DirectOmitEmpty><T1></T1><T2></T2></DirectOmitEmpty>`,
+		Value:     &DirectOmitEmpty{OmitEmpty: string("")},
+	},
+	{
+		ExpectXML: `<IndirAny><T1></T1><Any>hi</Any><T2></T2></IndirAny>`,
+		Value:     &IndirAny{Any: stringptr("hi")},
+	},
+	{
+		ExpectXML: `<IndirAny><T1></T1><Any></Any><T2></T2></IndirAny>`,
+		Value:     &IndirAny{Any: stringptr("")},
+	},
+	{
+		ExpectXML: `<IndirAny><T1></T1><T2></T2></IndirAny>`,
+		Value:     &IndirAny{Any: nil},
+	},
+	{
+		ExpectXML:   `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`,
+		Value:       &IfaceAny{Any: "hi"},
+		MarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IfaceAny><T1></T1><Any>hi</Any><T2></T2></IfaceAny>`,
+		Value:         &IfaceAny{Any: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<IfaceAny><T1></T1><T2></T2></IfaceAny>`,
+		Value:     &IfaceAny{Any: nil},
+	},
+	{
+		ExpectXML:     `<IfaceAny><T1></T1><T2></T2></IfaceAny>`,
+		Value:         &IfaceAny{Any: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML: `<DirectAny><T1></T1><Any>hi</Any><T2></T2></DirectAny>`,
+		Value:     &DirectAny{Any: string("hi")},
+	},
+	{
+		ExpectXML: `<DirectAny><T1></T1><Any></Any><T2></T2></DirectAny>`,
+		Value:     &DirectAny{Any: string("")},
+	},
+	{
+		ExpectXML:     `<IndirFoo><T1></T1><Foo>hi</Foo><T2></T2></IndirFoo>`,
+		Value:         &IndirAny{Any: stringptr("hi")},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IndirFoo><T1></T1><Foo></Foo><T2></T2></IndirFoo>`,
+		Value:         &IndirAny{Any: stringptr("")},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IndirFoo><T1></T1><T2></T2></IndirFoo>`,
+		Value:         &IndirAny{Any: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IfaceFoo><T1></T1><Foo>hi</Foo><T2></T2></IfaceFoo>`,
+		Value:         &IfaceAny{Any: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`,
+		Value:         &IfaceAny{Any: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<IfaceFoo><T1></T1><T2></T2></IfaceFoo>`,
+		Value:         &IfaceAny{Any: nil},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<DirectFoo><T1></T1><Foo>hi</Foo><T2></T2></DirectFoo>`,
+		Value:         &DirectAny{Any: string("hi")},
+		UnmarshalOnly: true,
+	},
+	{
+		ExpectXML:     `<DirectFoo><T1></T1><Foo></Foo><T2></T2></DirectFoo>`,
+		Value:         &DirectAny{Any: string("")},
+		UnmarshalOnly: true,
+	},
 }
 
 func TestMarshal(t *testing.T) {
@@ -1142,7 +1654,17 @@
 		}
 		data, err := Marshal(test.Value)
 		if err != nil {
-			t.Errorf("#%d: marshal(%#v): %s", idx, test.Value, err)
+			if test.MarshalError == "" {
+				t.Errorf("#%d: marshal(%#v): %s", idx, test.Value, err)
+				continue
+			}
+			if !strings.Contains(err.Error(), test.MarshalError) {
+				t.Errorf("#%d: marshal(%#v): %s, want %q", idx, test.Value, err, test.MarshalError)
+			}
+			continue
+		}
+		if test.MarshalError != "" {
+			t.Errorf("#%d: Marshal succeeded, want error %q", idx, test.MarshalError)
 			continue
 		}
 		if got, want := string(data), test.ExpectXML; got != want {
@@ -1268,8 +1790,16 @@
 		}
 
 		if err != nil {
-			t.Errorf("#%d: unexpected error: %#v", i, err)
-		} else if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
+			if test.UnmarshalError == "" {
+				t.Errorf("#%d: unmarshal(%#v): %s", i, test.ExpectXML, err)
+				continue
+			}
+			if !strings.Contains(err.Error(), test.UnmarshalError) {
+				t.Errorf("#%d: unmarshal(%#v): %s, want %q", i, test.ExpectXML, err, test.UnmarshalError)
+			}
+			continue
+		}
+		if got, want := dest, test.Value; !reflect.DeepEqual(got, want) {
 			t.Errorf("#%d: unmarshal(%q):\nhave %#v\nwant %#v", i, test.ExpectXML, got, want)
 		}
 	}
@@ -1898,7 +2428,10 @@
 	err := Unmarshal([]byte(data), &struct {
 		B byte `xml:"b,attr,omitempty"`
 	}{})
-	if err == nil {
-		t.Errorf("Unmarshal: expected error, got nil")
+
+	// For Go 1.8.1 we've restored the old "no errors reported" behavior.
+	// We'll try again in Go 1.9 to report errors.
+	if err != nil {
+		t.Errorf("Unmarshal: expected nil, got error")
 	}
 }
diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go
index 5a89d5f..799b57e 100644
--- a/src/encoding/xml/read.go
+++ b/src/encoding/xml/read.go
@@ -285,7 +285,8 @@
 		return nil
 	}
 
-	return copyValue(val, []byte(attr.Value))
+	copyValue(val, []byte(attr.Value))
+	return nil
 }
 
 var (
diff --git a/src/encoding/xml/xml_test.go b/src/encoding/xml/xml_test.go
index dad6ed9..f43a5e7 100644
--- a/src/encoding/xml/xml_test.go
+++ b/src/encoding/xml/xml_test.go
@@ -797,3 +797,37 @@
 		}
 	}
 }
+
+func TestIssue19333(t *testing.T) {
+	type X struct {
+		XMLName Name `xml:"X"`
+		A       int  `xml:",attr"`
+		C       int
+	}
+
+	var tests = []struct {
+		input string
+		ok    bool
+	}{
+		{`<X></X>`, true},
+		{`<X A=""></X>`, true},
+		{`<X A="bad"></X>`, true},
+		{`<X></X>`, true},
+		{`<X><C></C></X>`, false},
+		{`<X><C/></X>`, false},
+		{`<X><C>bad</C></X>`, false},
+	}
+
+	for _, tt := range tests {
+		err := Unmarshal([]byte(tt.input), new(X))
+		if tt.ok {
+			if err != nil {
+				t.Errorf("%s: unexpected error: %v", tt.input, err)
+			}
+		} else {
+			if err == nil {
+				t.Errorf("%s: unexpected success", tt.input)
+			}
+		}
+	}
+}
diff --git a/src/go/build/build.go b/src/go/build/build.go
index 1096354..fdd0735 100644
--- a/src/go/build/build.go
+++ b/src/go/build/build.go
@@ -266,7 +266,7 @@
 	}
 	if home := os.Getenv(env); home != "" {
 		def := filepath.Join(home, "go")
-		if def == runtime.GOROOT() {
+		if filepath.Clean(def) == filepath.Clean(runtime.GOROOT()) {
 			// Don't set the default GOPATH to GOROOT,
 			// as that will trigger warnings from the go tool.
 			return ""
diff --git a/src/image/png/reader.go b/src/image/png/reader.go
index 32f78f0..8299df5 100644
--- a/src/image/png/reader.go
+++ b/src/image/png/reader.go
@@ -612,6 +612,11 @@
 				}
 			}
 		case cbG8:
+			if d.useTransparent {
+				// Match error from Go 1.7 and earlier.
+				// Go 1.9 will decode this properly.
+				return nil, chunkOrderError
+			}
 			copy(gray.Pix[pixOffset:], cdat)
 			pixOffset += gray.Stride
 		case cbGA8:
diff --git a/src/image/png/reader_test.go b/src/image/png/reader_test.go
index b9e9f4d..503b5dc 100644
--- a/src/image/png/reader_test.go
+++ b/src/image/png/reader_test.go
@@ -629,3 +629,13 @@
 func BenchmarkDecodeInterlacing(b *testing.B) {
 	benchmarkDecode(b, "testdata/benchRGB-interlace.png", 4)
 }
+
+func TestIssue19553(t *testing.T) {
+	var buf = []byte{
+		0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x0b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x85, 0x2c, 0x88, 0x80, 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0x00, 0xff, 0x5b, 0x91, 0x22, 0xb5, 0x00, 0x00, 0x00, 0x02, 0x62, 0x4b, 0x47, 0x44, 0x00, 0xff, 0x87, 0x8f, 0xcc, 0xbf, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x0a, 0xf0, 0x01, 0x42, 0xac, 0x34, 0x98, 0x00, 0x00, 0x00, 0x07, 0x74, 0x49, 0x4d, 0x45, 0x07, 0xd5, 0x04, 0x02, 0x12, 0x11, 0x11, 0xf7, 0x65, 0x3d, 0x8b, 0x00, 0x00, 0x00, 0x4f, 0x49, 0x44, 0x41, 0x54, 0x08, 0xd7, 0x63, 0xf8, 0xff, 0xff, 0xff, 0xb9, 0xbd, 0x70, 0xf0, 0x8c, 0x01, 0xc8, 0xaf, 0x6e, 0x99, 0x02, 0x05, 0xd9, 0x7b, 0xc1, 0xfc, 0x6b, 0xff, 0xa1, 0xa0, 0x87, 0x30, 0xff, 0xd9, 0xde, 0xbd, 0xd5, 0x4b, 0xf7, 0xee, 0xfd, 0x0e, 0xe3, 0xef, 0xcd, 0x06, 0x19, 0x14, 0xf5, 0x1e, 0xce, 0xef, 0x01, 0x31, 0x92, 0xd7, 0x82, 0x41, 0x31, 0x9c, 0x3f, 0x07, 0x02, 0xee, 0xa1, 0xaa, 0xff, 0xff, 0x9f, 0xe1, 0xd9, 0x56, 0x30, 0xf8, 0x0e, 0xe5, 0x03, 0x00, 0xa9, 0x42, 0x84, 0x3d, 0xdf, 0x8f, 0xa6, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
+	}
+	_, err := Decode(bytes.NewReader(buf))
+	if err != chunkOrderError {
+		t.Errorf("Decode: expected chunkOrderError for transparent gray8, got %v", err)
+	}
+}
diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go
index 10384b6..f7c4ad2 100644
--- a/src/internal/testenv/testenv.go
+++ b/src/internal/testenv/testenv.go
@@ -138,6 +138,15 @@
 	}
 }
 
+var haveCGO bool
+
+// MustHaveCGO calls t.Skip if cgo is not available.
+func MustHaveCGO(t *testing.T) {
+	if !haveCGO {
+		t.Skipf("skipping test: no cgo")
+	}
+}
+
 // HasSymlink reports whether the current system can use os.Symlink.
 func HasSymlink() bool {
 	ok, _ := hasSymlink()
diff --git a/src/internal/testenv/testenv_cgo.go b/src/internal/testenv/testenv_cgo.go
new file mode 100644
index 0000000..e3d4d16
--- /dev/null
+++ b/src/internal/testenv/testenv_cgo.go
@@ -0,0 +1,11 @@
+// Copyright 2017 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.
+
+// +build cgo
+
+package testenv
+
+func init() {
+	haveCGO = true
+}
diff --git a/src/net/http/http.go b/src/net/http/http.go
index 826f7ff..b95ca89 100644
--- a/src/net/http/http.go
+++ b/src/net/http/http.go
@@ -20,7 +20,7 @@
 
 // aLongTimeAgo is a non-zero time, far in the past, used for
 // immediate cancelation of network operations.
-var aLongTimeAgo = time.Unix(233431200, 0)
+var aLongTimeAgo = time.Unix(1, 0)
 
 // TODO(bradfitz): move common stuff here. The other files have accumulated
 // generic http stuff in random places.
diff --git a/src/net/net.go b/src/net/net.go
index 81206ea..a8b5736 100644
--- a/src/net/net.go
+++ b/src/net/net.go
@@ -468,7 +468,7 @@
 var (
 	// aLongTimeAgo is a non-zero time, far in the past, used for
 	// immediate cancelation of dials.
-	aLongTimeAgo = time.Unix(233431200, 0)
+	aLongTimeAgo = time.Unix(1, 0)
 
 	// nonDeadline and noCancel are just zero values for
 	// readability with functions taking too many parameters.
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 3433745..bd20dd4 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -262,9 +262,13 @@
 		t.Fatalf("Start: %v", err)
 	}
 	go func() {
-		if err := cmd.Process.Kill(); err != nil {
-			t.Errorf("Kill: %v", err)
-		}
+		// We don't check the error return of Kill. It is
+		// possible that the process has already exited, in
+		// which case Kill will return an error "process
+		// already finished". The purpose of this test is to
+		// see whether the race detector reports an error; it
+		// doesn't matter whether this Kill succeeds or not.
+		cmd.Process.Kill()
 	}()
 	go func() {
 		// Send the wrong string, so that the child fails even
diff --git a/src/reflect/all_test.go b/src/reflect/all_test.go
index 0be306dc..382ad6b 100644
--- a/src/reflect/all_test.go
+++ b/src/reflect/all_test.go
@@ -1681,6 +1681,11 @@
 }
 
 // This will be index 3.
+func (p Point) NoArgs() {
+	// Exercise no-argument/no-result paths.
+}
+
+// This will be index 4.
 func (p Point) TotalDist(points ...Point) int {
 	tot := 0
 	for _, q := range points {
@@ -1709,6 +1714,15 @@
 		t.Errorf("Type MethodByName returned %d; want 275", i)
 	}
 
+	m, ok = TypeOf(p).MethodByName("NoArgs")
+	if !ok {
+		t.Fatalf("method by name failed")
+	}
+	n := len(m.Func.Call([]Value{ValueOf(p)}))
+	if n != 0 {
+		t.Errorf("NoArgs returned %d values; want 0", n)
+	}
+
 	i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(12)})[0].Int()
 	if i != 300 {
 		t.Errorf("Pointer Type Method returned %d; want 300", i)
@@ -1723,6 +1737,15 @@
 		t.Errorf("Pointer Type MethodByName returned %d; want 325", i)
 	}
 
+	m, ok = TypeOf(&p).MethodByName("NoArgs")
+	if !ok {
+		t.Fatalf("method by name failed")
+	}
+	n = len(m.Func.Call([]Value{ValueOf(&p)}))
+	if n != 0 {
+		t.Errorf("NoArgs returned %d values; want 0", n)
+	}
+
 	// Curried method of value.
 	tfunc := TypeOf((func(int) int)(nil))
 	v := ValueOf(p).Method(1)
@@ -1741,6 +1764,8 @@
 	if i != 375 {
 		t.Errorf("Value MethodByName returned %d; want 375", i)
 	}
+	v = ValueOf(p).MethodByName("NoArgs")
+	v.Call(nil)
 
 	// Curried method of pointer.
 	v = ValueOf(&p).Method(1)
@@ -1759,6 +1784,8 @@
 	if i != 425 {
 		t.Errorf("Pointer Value MethodByName returned %d; want 425", i)
 	}
+	v = ValueOf(&p).MethodByName("NoArgs")
+	v.Call(nil)
 
 	// Curried method of interface value.
 	// Have to wrap interface value in a struct to get at it.
@@ -1808,6 +1835,9 @@
 	if i != 275 {
 		t.Errorf("Value MethodByName returned %d; want 275", i)
 	}
+	v = ValueOf(p).MethodByName("NoArgs")
+	ValueOf(v.Interface()).Call(nil)
+	v.Interface().(func())()
 
 	// Curried method of pointer.
 	v = ValueOf(&p).Method(1)
@@ -1826,6 +1856,9 @@
 	if i != 325 {
 		t.Errorf("Pointer Value MethodByName returned %d; want 325", i)
 	}
+	v = ValueOf(&p).MethodByName("NoArgs")
+	ValueOf(v.Interface()).Call(nil)
+	v.Interface().(func())()
 
 	// Curried method of pointer to pointer.
 	pp := &p
@@ -1881,7 +1914,7 @@
 
 	// Curried method of value.
 	tfunc := TypeOf((func(...Point) int)(nil))
-	v := ValueOf(p).Method(3)
+	v := ValueOf(p).Method(4)
 	if tt := v.Type(); tt != tfunc {
 		t.Errorf("Variadic Method Type is %s; want %s", tt, tfunc)
 	}
@@ -2478,17 +2511,24 @@
 }
 
 func TestPtrTo(t *testing.T) {
+	// This block of code means that the ptrToThis field of the
+	// reflect data for *unsafe.Pointer is non zero, see
+	// https://golang.org/issue/19003
+	var x unsafe.Pointer
+	var y = &x
+	var z = &y
+
 	var i int
 
-	typ := TypeOf(i)
+	typ := TypeOf(z)
 	for i = 0; i < 100; i++ {
 		typ = PtrTo(typ)
 	}
 	for i = 0; i < 100; i++ {
 		typ = typ.Elem()
 	}
-	if typ != TypeOf(i) {
-		t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(i))
+	if typ != TypeOf(z) {
+		t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(z))
 	}
 }
 
@@ -6053,7 +6093,6 @@
 	})
 }
 
-
 type Tint int
 
 type Tint2 = Tint
@@ -6086,4 +6125,3 @@
 		t.Errorf("Talias2 print:\nhave: %s\nwant: %s", out, want)
 	}
 }
-
diff --git a/src/reflect/type.go b/src/reflect/type.go
index fbfda3a..4085909 100644
--- a/src/reflect/type.go
+++ b/src/reflect/type.go
@@ -1463,6 +1463,7 @@
 	pp := *prototype
 
 	pp.str = resolveReflectName(newName(s, "", "", false))
+	pp.ptrToThis = 0
 
 	// For the type structures linked into the binary, the
 	// compiler provides a good hash of the string.
diff --git a/src/reflect/value.go b/src/reflect/value.go
index 1abfbe6..125f04e 100644
--- a/src/reflect/value.go
+++ b/src/reflect/value.go
@@ -630,8 +630,11 @@
 	args := framePool.Get().(unsafe.Pointer)
 
 	// Copy in receiver and rest of args.
+	// Avoid constructing out-of-bounds pointers if there are no args.
 	storeRcvr(rcvr, args)
-	typedmemmovepartial(frametype, unsafe.Pointer(uintptr(args)+ptrSize), frame, ptrSize, argSize-ptrSize)
+	if argSize-ptrSize > 0 {
+		typedmemmovepartial(frametype, unsafe.Pointer(uintptr(args)+ptrSize), frame, ptrSize, argSize-ptrSize)
+	}
 
 	// Call.
 	call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))
@@ -641,15 +644,18 @@
 	// a receiver) is different from the layout of the fn call, which has
 	// a receiver.
 	// Ignore any changes to args and just copy return values.
-	callerRetOffset := retOffset - ptrSize
-	if runtime.GOARCH == "amd64p32" {
-		callerRetOffset = align(argSize-ptrSize, 8)
+	// Avoid constructing out-of-bounds pointers if there are no return values.
+	if frametype.size-retOffset > 0 {
+		callerRetOffset := retOffset - ptrSize
+		if runtime.GOARCH == "amd64p32" {
+			callerRetOffset = align(argSize-ptrSize, 8)
+		}
+		typedmemmovepartial(frametype,
+			unsafe.Pointer(uintptr(frame)+callerRetOffset),
+			unsafe.Pointer(uintptr(args)+retOffset),
+			retOffset,
+			frametype.size-retOffset)
 	}
-	typedmemmovepartial(frametype,
-		unsafe.Pointer(uintptr(frame)+callerRetOffset),
-		unsafe.Pointer(uintptr(args)+retOffset),
-		retOffset,
-		frametype.size-retOffset)
 
 	// This is untyped because the frame is really a stack, even
 	// though it's a heap object.
diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go
index 97deed8..182c84b 100644
--- a/src/runtime/crash_unix_test.go
+++ b/src/runtime/crash_unix_test.go
@@ -9,6 +9,7 @@
 import (
 	"bytes"
 	"internal/testenv"
+	"io"
 	"io/ioutil"
 	"os"
 	"os/exec"
@@ -153,6 +154,78 @@
 }
 `
 
+func TestPanicSystemstack(t *testing.T) {
+	// Test that GOTRACEBACK=crash prints both the system and user
+	// stack of other threads.
+
+	// The GOTRACEBACK=crash handler takes 0.1 seconds even if
+	// it's not writing a core file and potentially much longer if
+	// it is. Skip in short mode.
+	if testing.Short() {
+		t.Skip("Skipping in short mode (GOTRACEBACK=crash is slow)")
+	}
+
+	t.Parallel()
+	cmd := exec.Command(os.Args[0], "testPanicSystemstackInternal")
+	cmd = testEnv(cmd)
+	cmd.Env = append(cmd.Env, "GOTRACEBACK=crash")
+	pr, pw, err := os.Pipe()
+	if err != nil {
+		t.Fatal("creating pipe: ", err)
+	}
+	cmd.Stderr = pw
+	if err := cmd.Start(); err != nil {
+		t.Fatal("starting command: ", err)
+	}
+	defer cmd.Process.Wait()
+	defer cmd.Process.Kill()
+	if err := pw.Close(); err != nil {
+		t.Log("closing write pipe: ", err)
+	}
+	defer pr.Close()
+
+	// Wait for "x\nx\n" to indicate readiness.
+	buf := make([]byte, 4)
+	_, err = io.ReadFull(pr, buf)
+	if err != nil || string(buf) != "x\nx\n" {
+		t.Fatal("subprocess failed; output:\n", string(buf))
+	}
+
+	// Send SIGQUIT.
+	if err := cmd.Process.Signal(syscall.SIGQUIT); err != nil {
+		t.Fatal("signaling subprocess: ", err)
+	}
+
+	// Get traceback.
+	tb, err := ioutil.ReadAll(pr)
+	if err != nil {
+		t.Fatal("reading traceback from pipe: ", err)
+	}
+
+	// Traceback should have two testPanicSystemstackInternal's
+	// and two blockOnSystemStackInternal's.
+	if bytes.Count(tb, []byte("testPanicSystemstackInternal")) != 2 {
+		t.Fatal("traceback missing user stack:\n", string(tb))
+	} else if bytes.Count(tb, []byte("blockOnSystemStackInternal")) != 2 {
+		t.Fatal("traceback missing system stack:\n", string(tb))
+	}
+}
+
+func init() {
+	if len(os.Args) >= 2 && os.Args[1] == "testPanicSystemstackInternal" {
+		// Get two threads running on the system stack with
+		// something recognizable in the stack trace.
+		runtime.GOMAXPROCS(2)
+		go testPanicSystemstackInternal()
+		testPanicSystemstackInternal()
+	}
+}
+
+func testPanicSystemstackInternal() {
+	runtime.BlockOnSystemStack()
+	os.Exit(1) // Should be unreachable.
+}
+
 func TestSignalExitStatus(t *testing.T) {
 	testenv.MustHaveGoBuild(t)
 	exe, err := buildTestProg(t, "testprog")
diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go
index 9b76555..3b33c84 100644
--- a/src/runtime/export_test.go
+++ b/src/runtime/export_test.go
@@ -245,3 +245,16 @@
 
 	return
 }
+
+// BlockOnSystemStack switches to the system stack, prints "x\n" to
+// stderr, and blocks in a stack containing
+// "runtime.blockOnSystemStackInternal".
+func BlockOnSystemStack() {
+	systemstack(blockOnSystemStackInternal)
+}
+
+func blockOnSystemStackInternal() {
+	print("x\n")
+	lock(&deadlock)
+	lock(&deadlock)
+}
diff --git a/src/runtime/mgc.go b/src/runtime/mgc.go
index 0b996d8..cd57720 100644
--- a/src/runtime/mgc.go
+++ b/src/runtime/mgc.go
@@ -628,10 +628,12 @@
 //go:nowritebarrier
 func (c *gcControllerState) enlistWorker() {
 	// If there are idle Ps, wake one so it will run an idle worker.
-	if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
-		wakep()
-		return
-	}
+	// NOTE: This is suspected of causing deadlocks. See golang.org/issue/19112.
+	//
+	//	if atomic.Load(&sched.npidle) != 0 && atomic.Load(&sched.nmspinning) == 0 {
+	//		wakep()
+	//		return
+	//	}
 
 	// There are no idle Ps. If we need more dedicated workers,
 	// try to preempt a running P so it will switch to a worker.
diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go
index 40c0e85..5d0bf81 100644
--- a/src/runtime/runtime1.go
+++ b/src/runtime/runtime1.go
@@ -260,6 +260,12 @@
 		throw("atomicor8")
 	}
 
+	m = [4]byte{0xff, 0xff, 0xff, 0xff}
+	atomic.And8(&m[1], 0x1)
+	if m[0] != 0xff || m[1] != 0x1 || m[2] != 0xff || m[3] != 0xff {
+		throw("atomicand8")
+	}
+
 	*(*uint64)(unsafe.Pointer(&j)) = ^uint64(0)
 	if j == j {
 		throw("float64nan")
diff --git a/src/runtime/sema.go b/src/runtime/sema.go
index 576a1fb..37318ff 100644
--- a/src/runtime/sema.go
+++ b/src/runtime/sema.go
@@ -171,6 +171,7 @@
 			for x := root.head; x != nil; x = x.next {
 				if x.elem == unsafe.Pointer(addr) {
 					x.acquiretime = t0
+					break
 				}
 			}
 			mutexevent(t0-s.acquiretime, 3)
diff --git a/src/runtime/signal_sighandler.go b/src/runtime/signal_sighandler.go
index 5af12d7..758e42f 100644
--- a/src/runtime/signal_sighandler.go
+++ b/src/runtime/signal_sighandler.go
@@ -101,7 +101,7 @@
 		if crashing > 0 && gp != _g_.m.curg && _g_.m.curg != nil && readgstatus(_g_.m.curg)&^_Gscan == _Grunning {
 			// tracebackothers on original m skipped this one; trace it now.
 			goroutineheader(_g_.m.curg)
-			traceback(^uintptr(0), ^uintptr(0), 0, gp)
+			traceback(^uintptr(0), ^uintptr(0), 0, _g_.m.curg)
 		} else if crashing == 0 {
 			tracebackothers(gp)
 			print("\n")
diff --git a/src/text/template/multi_test.go b/src/text/template/multi_test.go
index 8142f00..5d8c08f 100644
--- a/src/text/template/multi_test.go
+++ b/src/text/template/multi_test.go
@@ -363,7 +363,7 @@
 		{[]string{"{{.}}", ""}, "twice", ""},
 	}
 
-	for _, c := range cases {
+	for i, c := range cases {
 		root := New("root")
 
 		var (
@@ -378,10 +378,43 @@
 		}
 		buf := &bytes.Buffer{}
 		if err := m.Execute(buf, c.in); err != nil {
-			t.Fatal(err)
+			t.Error(i, err)
+			continue
 		}
 		if buf.String() != c.want {
 			t.Errorf("expected string %q: got %q", c.want, buf.String())
 		}
 	}
 }
+
+// Issue 19249 was a regression in 1.8 caused by the handling of empty
+// templates added in that release, which got different answers depending
+// on the order templates appeared in the internal map.
+func TestIssue19294(t *testing.T) {
+	// The empty block in "xhtml" should be replaced during execution
+	// by the contents of "stylesheet", but if the internal map associating
+	// names with templates is built in the wrong order, the empty block
+	// looks non-empty and this doesn't happen.
+	var inlined = map[string]string{
+		"stylesheet": `{{define "stylesheet"}}stylesheet{{end}}`,
+		"xhtml":      `{{block "stylesheet" .}}{{end}}`,
+	}
+	all := []string{"stylesheet", "xhtml"}
+	for i := 0; i < 100; i++ {
+		res, err := New("title.xhtml").Parse(`{{template "xhtml" .}}`)
+		if err != nil {
+			t.Fatal(err)
+		}
+		for _, name := range all {
+			_, err := res.New(name).Parse(inlined[name])
+			if err != nil {
+				t.Fatal(err)
+			}
+		}
+		var buf bytes.Buffer
+		res.Execute(&buf, 0)
+		if buf.String() != "stylesheet" {
+			t.Fatalf("iteration %d: got %q; expected %q", i, buf.String(), "stylesheet")
+		}
+	}
+}
diff --git a/src/text/template/template.go b/src/text/template/template.go
index b6fceb1..3b4f34b 100644
--- a/src/text/template/template.go
+++ b/src/text/template/template.go
@@ -127,7 +127,7 @@
 	// Even if nt == t, we need to install it in the common.tmpl map.
 	if replace, err := t.associate(nt, tree); err != nil {
 		return nil, err
-	} else if replace {
+	} else if replace || nt.Tree == nil {
 		nt.Tree = tree
 	}
 	return nt, nil
@@ -215,7 +215,7 @@
 	if new.common != t.common {
 		panic("internal error: associate not common")
 	}
-	if t.tmpl[new.name] != nil && parse.IsEmptyTree(tree.Root) && t.Tree != nil {
+	if old := t.tmpl[new.name]; old != nil && parse.IsEmptyTree(tree.Root) && old.Tree != nil {
 		// If a template by that name exists,
 		// don't replace it with an empty template.
 		return false, nil
diff --git a/src/time/format_test.go b/src/time/format_test.go
index 219c2ca..d0013bc 100644
--- a/src/time/format_test.go
+++ b/src/time/format_test.go
@@ -245,27 +245,45 @@
 	}
 }
 
+// TestParseInLocation checks that the Parse and ParseInLocation
+// functions do not get confused by the fact that AST (Arabia Standard
+// Time) and AST (Atlantic Standard Time) are different time zones,
+// even though they have the same abbreviation.
+//
+// ICANN has been slowly phasing out invented abbreviation in favor of
+// numeric time zones (for example, the Asia/Baghdad time zone
+// abbreviation got changed from AST to +03 in the 2017a tzdata
+// release); but we still want to make sure that the time package does
+// not get confused on systems with slightly older tzdata packages.
 func TestParseInLocation(t *testing.T) {
-	// Check that Parse (and ParseInLocation) understand that
-	// Feb 01 AST (Arabia Standard Time) and Feb 01 AST (Atlantic Standard Time)
-	// are in different time zones even though both are called AST
 
 	baghdad, err := LoadLocation("Asia/Baghdad")
 	if err != nil {
 		t.Fatal(err)
 	}
 
-	t1, err := ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", baghdad)
+	var t1, t2 Time
+
+	t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", baghdad)
 	if err != nil {
 		t.Fatal(err)
 	}
-	t2 := Date(2013, February, 1, 00, 00, 00, 0, baghdad)
-	if t1 != t2 {
-		t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad) = %v, want %v", t1, t2)
-	}
+
 	_, offset := t1.Zone()
-	if offset != 3*60*60 {
-		t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad).Zone = _, %d, want _, %d", offset, 3*60*60)
+
+	// A zero offset means that ParseInLocation did not recognize the
+	// 'AST' abbreviation as matching the current location (Baghdad,
+	// where we'd expect a +03 hrs offset); likely because we're using
+	// a recent tzdata release (2017a or newer).
+	// If it happens, skip the Baghdad test.
+	if offset != 0 {
+		t2 = Date(2013, February, 1, 00, 00, 00, 0, baghdad)
+		if t1 != t2 {
+			t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad) = %v, want %v", t1, t2)
+		}
+		if offset != 3*60*60 {
+			t.Fatalf("ParseInLocation(Feb 01 2013 AST, Baghdad).Zone = _, %d, want _, %d", offset, 3*60*60)
+		}
 	}
 
 	blancSablon, err := LoadLocation("America/Blanc-Sablon")
@@ -273,6 +291,9 @@
 		t.Fatal(err)
 	}
 
+	// In this case 'AST' means 'Atlantic Standard Time', and we
+	// expect the abbreviation to correctly match the american
+	// location.
 	t1, err = ParseInLocation("Jan 02 2006 MST", "Feb 01 2013 AST", blancSablon)
 	if err != nil {
 		t.Fatal(err)
diff --git a/src/vendor/golang_org/x/crypto/curve25519/const_amd64.h b/src/vendor/golang_org/x/crypto/curve25519/const_amd64.h
new file mode 100644
index 0000000..80ad222
--- /dev/null
+++ b/src/vendor/golang_org/x/crypto/curve25519/const_amd64.h
@@ -0,0 +1,8 @@
+// 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.
+
+// This code was translated into a form compatible with 6a from the public
+// domain sources in SUPERCOP: http://bench.cr.yp.to/supercop.html
+
+#define REDMASK51     0x0007FFFFFFFFFFFF
diff --git a/src/vendor/golang_org/x/crypto/curve25519/const_amd64.s b/src/vendor/golang_org/x/crypto/curve25519/const_amd64.s
index 797f9b0..0ad5398 100644
--- a/src/vendor/golang_org/x/crypto/curve25519/const_amd64.s
+++ b/src/vendor/golang_org/x/crypto/curve25519/const_amd64.s
@@ -7,8 +7,8 @@
 
 // +build amd64,!gccgo,!appengine
 
-DATA ·REDMASK51(SB)/8, $0x0007FFFFFFFFFFFF
-GLOBL ·REDMASK51(SB), 8, $8
+// These constants cannot be encoded in non-MOVQ immediates.
+// We access them directly from memory instead.
 
 DATA ·_121666_213(SB)/8, $996687872
 GLOBL ·_121666_213(SB), 8, $8
diff --git a/src/vendor/golang_org/x/crypto/curve25519/freeze_amd64.s b/src/vendor/golang_org/x/crypto/curve25519/freeze_amd64.s
index 932800b..536479b 100644
--- a/src/vendor/golang_org/x/crypto/curve25519/freeze_amd64.s
+++ b/src/vendor/golang_org/x/crypto/curve25519/freeze_amd64.s
@@ -7,6 +7,8 @@
 
 // +build amd64,!gccgo,!appengine
 
+#include "const_amd64.h"
+
 // func freeze(inout *[5]uint64)
 TEXT ·freeze(SB),7,$0-8
 	MOVQ inout+0(FP), DI
@@ -16,7 +18,7 @@
 	MOVQ 16(DI),CX
 	MOVQ 24(DI),R8
 	MOVQ 32(DI),R9
-	MOVQ ·REDMASK51(SB),AX
+	MOVQ $REDMASK51,AX
 	MOVQ AX,R10
 	SUBQ $18,R10
 	MOVQ $3,R11
diff --git a/src/vendor/golang_org/x/crypto/curve25519/ladderstep_amd64.s b/src/vendor/golang_org/x/crypto/curve25519/ladderstep_amd64.s
index ee7b36c..7074e5c 100644
--- a/src/vendor/golang_org/x/crypto/curve25519/ladderstep_amd64.s
+++ b/src/vendor/golang_org/x/crypto/curve25519/ladderstep_amd64.s
@@ -7,6 +7,8 @@
 
 // +build amd64,!gccgo,!appengine
 
+#include "const_amd64.h"
+
 // func ladderstep(inout *[5][5]uint64)
 TEXT ·ladderstep(SB),0,$296-8
 	MOVQ inout+0(FP),DI
@@ -118,7 +120,7 @@
 	MULQ 72(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -233,7 +235,7 @@
 	MULQ 32(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -438,7 +440,7 @@
 	MULQ 72(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -588,7 +590,7 @@
 	MULQ 32(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -728,7 +730,7 @@
 	MULQ 152(DI)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -843,7 +845,7 @@
 	MULQ 192(DI)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -993,7 +995,7 @@
 	MULQ 32(DI)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -1143,7 +1145,7 @@
 	MULQ 112(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
@@ -1329,7 +1331,7 @@
 	MULQ 192(SP)
 	ADDQ AX,R12
 	ADCQ DX,R13
-	MOVQ ·REDMASK51(SB),DX
+	MOVQ $REDMASK51,DX
 	SHLQ $13,CX:SI
 	ANDQ DX,SI
 	SHLQ $13,R9:R8
diff --git a/src/vendor/golang_org/x/crypto/curve25519/mul_amd64.s b/src/vendor/golang_org/x/crypto/curve25519/mul_amd64.s
index 33ce57d..b162e65 100644
--- a/src/vendor/golang_org/x/crypto/curve25519/mul_amd64.s
+++ b/src/vendor/golang_org/x/crypto/curve25519/mul_amd64.s
@@ -7,6 +7,8 @@
 
 // +build amd64,!gccgo,!appengine
 
+#include "const_amd64.h"
+
 // func mul(dest, a, b *[5]uint64)
 TEXT ·mul(SB),0,$16-24
 	MOVQ dest+0(FP), DI
@@ -121,7 +123,7 @@
 	MULQ 32(CX)
 	ADDQ AX,R14
 	ADCQ DX,R15
-	MOVQ ·REDMASK51(SB),SI
+	MOVQ $REDMASK51,SI
 	SHLQ $13,R9:R8
 	ANDQ SI,R8
 	SHLQ $13,R11:R10
diff --git a/src/vendor/golang_org/x/crypto/curve25519/square_amd64.s b/src/vendor/golang_org/x/crypto/curve25519/square_amd64.s
index 3a92804..4e864a8 100644
--- a/src/vendor/golang_org/x/crypto/curve25519/square_amd64.s
+++ b/src/vendor/golang_org/x/crypto/curve25519/square_amd64.s
@@ -7,6 +7,8 @@
 
 // +build amd64,!gccgo,!appengine
 
+#include "const_amd64.h"
+
 // func square(out, in *[5]uint64)
 TEXT ·square(SB),7,$0-16
 	MOVQ out+0(FP), DI
@@ -84,7 +86,7 @@
 	MULQ 32(SI)
 	ADDQ AX,R13
 	ADCQ DX,R14
-	MOVQ ·REDMASK51(SB),SI
+	MOVQ $REDMASK51,SI
 	SHLQ $13,R8:CX
 	ANDQ SI,CX
 	SHLQ $13,R10:R9
diff --git a/test/fixedbugs/bug19403.go b/test/fixedbugs/bug19403.go
new file mode 100644
index 0000000..94c0fb4
--- /dev/null
+++ b/test/fixedbugs/bug19403.go
@@ -0,0 +1,134 @@
+// run
+
+// Copyright 2017 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.
+
+// Test for golang.org/issue/19403.
+// F15 should not be clobbered by float-to-int conversion on ARM.
+// This test requires enough locals that can be put in registers that the compiler can choose to use F15.
+package main
+
+var count float32 = 16
+var i0 int
+var i1 int
+var i2 int
+var i3 int
+var i4 int
+var i5 int
+var i6 int
+var i7 int
+var i8 int
+var i9 int
+var i10 int
+var i11 int
+var i12 int
+var i13 int
+var i14 int
+var i15 int
+var i16 int
+
+func main() {
+	var f0 float32 = 0.0
+	var f1 float32 = 1.0
+	var f2 float32 = 2.0
+	var f3 float32 = 3.0
+	var f4 float32 = 4.0
+	var f5 float32 = 5.0
+	var f6 float32 = 6.0
+	var f7 float32 = 7.0
+	var f8 float32 = 8.0
+	var f9 float32 = 9.0
+	var f10 float32 = 10.0
+	var f11 float32 = 11.0
+	var f12 float32 = 12.0
+	var f13 float32 = 13.0
+	var f14 float32 = 14.0
+	var f15 float32 = 15.0
+	var f16 float32 = 16.0
+	i0 = int(f0)
+	i1 = int(f1)
+	i2 = int(f2)
+	i3 = int(f3)
+	i4 = int(f4)
+	i5 = int(f5)
+	i6 = int(f6)
+	i7 = int(f7)
+	i8 = int(f8)
+	i9 = int(f9)
+	i10 = int(f10)
+	i11 = int(f11)
+	i12 = int(f12)
+	i13 = int(f13)
+	i14 = int(f14)
+	i15 = int(f15)
+	i16 = int(f16)
+	if f16 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f15 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f14 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f13 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f12 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f11 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f10 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f9 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f8 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f7 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f6 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f5 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f4 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f3 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f2 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f1 != count {
+		panic("fail")
+	}
+	count -= 1
+	if f0 != count {
+		panic("fail")
+	}
+	count -= 1
+}
diff --git a/test/fixedbugs/issue18915.go b/test/fixedbugs/issue18915.go
new file mode 100644
index 0000000..a432bbc
--- /dev/null
+++ b/test/fixedbugs/issue18915.go
@@ -0,0 +1,21 @@
+// errorcheck
+
+// Copyright 2017 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.
+
+// Make sure error message for invalid conditions
+// or tags are consistent with earlier Go versions.
+
+package p
+
+func _() {
+	if a := 10 { // ERROR "a := 10 used as value"
+	}
+
+	for b := 10 { // ERROR "b := 10 used as value"
+	}
+
+	switch c := 10 { // ERROR "c := 10 used as value"
+	}
+}
diff --git a/test/fixedbugs/issue19137.go b/test/fixedbugs/issue19137.go
new file mode 100644
index 0000000..946f029
--- /dev/null
+++ b/test/fixedbugs/issue19137.go
@@ -0,0 +1,35 @@
+// compile
+
+// Copyright 2017 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.
+
+// Issue 19137: folding address into load/store causes
+// odd offset on ARM64.
+
+package p
+
+type T struct {
+	p *int
+	a [2]byte
+	b [6]byte // not 4-byte aligned
+}
+
+func f(b [6]byte) T {
+	var x [1000]int // a large stack frame
+	_ = x
+	return T{b: b}
+}
+
+// Arg symbol's base address may be not at an aligned offset to
+// SP. Folding arg's address into load/store may cause odd offset.
+func move(a, b [20]byte) [20]byte {
+	var x [1000]int // a large stack frame
+	_ = x
+	return b // b is not 8-byte aligned to SP
+}
+func zero() ([20]byte, [20]byte) {
+	var x [1000]int // a large stack frame
+	_ = x
+	return [20]byte{}, [20]byte{} // the second return value is not 8-byte aligned to SP
+}
diff --git a/test/fixedbugs/issue19168.go b/test/fixedbugs/issue19168.go
new file mode 100644
index 0000000..b94b1d0
--- /dev/null
+++ b/test/fixedbugs/issue19168.go
@@ -0,0 +1,58 @@
+// errorcheck -0 -l -d=wb
+
+// Copyright 2017 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
+
+import (
+	"reflect"
+	"unsafe"
+
+	reflect2 "reflect"
+)
+
+func sink(e interface{})
+
+func a(hdr *reflect.SliceHeader, p *byte) {
+	hdr.Data = uintptr(unsafe.Pointer(p)) // ERROR "write barrier"
+}
+
+func b(hdr *reflect.StringHeader, p *byte) {
+	hdr.Data = uintptr(unsafe.Pointer(p)) // ERROR "write barrier"
+}
+
+func c(hdrs *[1]reflect.SliceHeader, p *byte) {
+	hdrs[0].Data = uintptr(unsafe.Pointer(p)) // ERROR "write barrier"
+}
+
+func d(hdr *struct{ s reflect.StringHeader }, p *byte) {
+	hdr.s.Data = uintptr(unsafe.Pointer(p)) // ERROR "write barrier"
+}
+
+func e(p *byte) (resHeap, resStack string) {
+	sink(&resHeap)
+
+	hdr := (*reflect.StringHeader)(unsafe.Pointer(&resHeap))
+	hdr.Data = uintptr(unsafe.Pointer(p)) // ERROR "write barrier"
+
+	// No write barrier for non-escaping stack vars.
+	hdr = (*reflect.StringHeader)(unsafe.Pointer(&resStack))
+	hdr.Data = uintptr(unsafe.Pointer(p))
+
+	return
+}
+
+func f(hdr *reflect2.SliceHeader, p *byte) {
+	hdr.Data = uintptr(unsafe.Pointer(p)) // ERROR "write barrier"
+}
+
+type SliceHeader struct {
+	Data uintptr
+}
+
+func g(hdr *SliceHeader, p *byte) {
+	// No write barrier for lookalike SliceHeader.
+	hdr.Data = uintptr(unsafe.Pointer(p))
+}
diff --git a/test/fixedbugs/issue19182.go b/test/fixedbugs/issue19182.go
new file mode 100644
index 0000000..3a90ff4
--- /dev/null
+++ b/test/fixedbugs/issue19182.go
@@ -0,0 +1,36 @@
+// run
+
+// Copyright 2017 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 main
+
+import (
+	"fmt"
+	"runtime"
+	"sync/atomic"
+	"time"
+)
+
+var a uint64 = 0
+
+func main() {
+	runtime.GOMAXPROCS(2) // With just 1, infinite loop never yields
+
+	go func() {
+		for {
+			atomic.AddUint64(&a, uint64(1))
+		}
+	}()
+
+	time.Sleep(10 * time.Millisecond) // Short sleep is enough in passing case
+	i, val := 0, atomic.LoadUint64(&a)
+	for ; val == 0 && i < 100; val, i = atomic.LoadUint64(&a), i+1 {
+		time.Sleep(100 * time.Millisecond)
+	}
+	if val == 0 {
+		fmt.Printf("Failed to observe atomic increment after %d tries\n", i)
+	}
+
+}
diff --git a/test/fixedbugs/issue19201.go b/test/fixedbugs/issue19201.go
new file mode 100644
index 0000000..e370d55
--- /dev/null
+++ b/test/fixedbugs/issue19201.go
@@ -0,0 +1,52 @@
+// run
+
+// Copyright 2017 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 main
+
+import (
+	"encoding/binary"
+)
+
+var (
+	ch1 = make(chan int)
+	ch2 = make(chan int)
+
+	bin  = []byte("a\000\000\001")
+	want = binary.BigEndian.Uint32(bin)
+
+	c consumer = noopConsumer{}
+)
+
+type msg struct {
+	code uint32
+}
+
+type consumer interface {
+	consume(msg)
+}
+
+type noopConsumer struct{}
+
+func (noopConsumer) consume(msg) {}
+
+func init() {
+	close(ch1)
+}
+
+func main() {
+	var m msg
+	m.code = binary.BigEndian.Uint32(bin)
+
+	select {
+	case <-ch1:
+		c.consume(m)
+		if m.code != want {
+			// can not use m.code here, or it will work
+			panic("BigEndian read failed")
+		}
+	case <-ch2:
+	}
+}
diff --git a/test/fixedbugs/issue19217.go b/test/fixedbugs/issue19217.go
new file mode 100644
index 0000000..9679406
--- /dev/null
+++ b/test/fixedbugs/issue19217.go
@@ -0,0 +1,39 @@
+// compile
+
+// Copyright 2017 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 foo
+
+import (
+	"encoding/binary"
+)
+
+type DbBuilder struct {
+	arr []int
+}
+
+func (bld *DbBuilder) Finish() error {
+	defer bld.Finish()
+
+	var hash []byte
+	for _, ixw := range bld.arr {
+		for {
+			if ixw != 0 {
+				panic("ixw != 0")
+			}
+			ixw--
+		insertOne:
+			for {
+				for i := 0; i < 1; i++ {
+					if binary.LittleEndian.Uint16(hash[i:]) == 0 {
+						break insertOne
+					}
+				}
+			}
+		}
+	}
+
+	return nil
+}
diff --git a/test/fixedbugs/issue19323.go b/test/fixedbugs/issue19323.go
new file mode 100644
index 0000000..f90af66
--- /dev/null
+++ b/test/fixedbugs/issue19323.go
@@ -0,0 +1,19 @@
+// errorcheck
+
+// Copyright 2017 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 g() {}
+
+func f() {
+	g()[:] // ERROR "g.. used as value"
+}
+
+func g2() ([]byte, []byte) { return nil, nil }
+
+func f2() {
+	g2()[:] // ERROR "multiple-value g2.. in single-value context"
+}
diff --git a/test/fixedbugs/issue19743.go b/test/fixedbugs/issue19743.go
new file mode 100644
index 0000000..e57b19c
--- /dev/null
+++ b/test/fixedbugs/issue19743.go
@@ -0,0 +1,31 @@
+// errorcheck -0 -m -l
+
+// Copyright 2017 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 foo
+
+// Escape analysis needs to treat the uintptr-typed reflect.*Header fields as pointers.
+
+import (
+	"reflect"
+	"unsafe"
+)
+
+type immutableBytes []byte
+
+// Bug was failure to leak param b.
+func toString(b immutableBytes) string { // ERROR "leaking param: b$"
+	var s string
+	if len(b) == 0 {
+		return s
+	}
+
+	strHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))         // ERROR "toString &s does not escape$"
+	strHeader.Data = (*reflect.SliceHeader)(unsafe.Pointer(&b)).Data // ERROR "toString &b does not escape$"
+
+	l := len(b)
+	strHeader.Len = l
+	return s
+}
diff --git a/test/fixedbugs/issue6036.go b/test/fixedbugs/issue6036.go
index 795b223..8ebef5a 100644
--- a/test/fixedbugs/issue6036.go
+++ b/test/fixedbugs/issue6036.go
@@ -1,4 +1,4 @@
-// +build amd64
+// +build !386,!arm,!mips,!mipsle,!amd64p32
 // compile
 
 // Copyright 2013 The Go Authors. All rights reserved.
diff --git a/test/writebarrier.go b/test/writebarrier.go
index 6460a6f..13f7b54 100644
--- a/test/writebarrier.go
+++ b/test/writebarrier.go
@@ -220,3 +220,19 @@
 	*p = x // no barrier
 	return
 }
+
+type T23 struct {
+	p *int
+	a int
+}
+
+var t23 T23
+var i23 int
+
+func f23() {
+	// zeroing global needs write barrier for the hybrid barrier.
+	t23 = T23{} // ERROR "write barrier"
+	// also test partial assignments
+	t23 = T23{a: 1}    // ERROR "write barrier"
+	t23 = T23{p: &i23} // ERROR "write barrier"
+}