[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#862158: unblock: golang-1.8/1.8.1-1



Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock

Dear release team,

please unblock golang-1.8 so the version to be released with stretch can
be upgraded to bugfix release 1.8.1-1, replacing release candidate
1.8~rc3-1.

Changes between golang 1.8 and 1.8.1[1]:

> go1.8.1 (released 2017/04/07) includes fixes to the compiler, linker,
> runtime, documentation, go command and the crypto/tls, encoding/xml,
> image/png, net, net/http, reflect, text/template, and time packages.

I haven't found any summary describing changes between golang 1.8RC3 and
1.8, so I ran "git log --decorate go1.8rc3..go1.8" and attached the
output. I have also attached the debdiff.

Cheers,
-Hilko

[1] https://golang.org/doc/devel/release.html#go1.8.minor
commit cd6b6202dd1559b3ac63179b45f1833fcfbe7eca (tag: go1.8)
Author: Chris Broadfoot <cbro@golang.org>
Date:   Thu Feb 16 08:41:18 2017 -0800

    [release-branch.go1.8] go1.8
    
    Change-Id: If1e38f02db86449abd4c8a57988d9825b1cf2511
    Reviewed-on: https://go-review.googlesource.com/37132
    Run-TryBot: Chris Broadfoot <cbro@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Russ Cox <rsc@golang.org>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 606eb9b0c118815dcbc68f224ec4485faf322c96
Author: Chris Broadfoot <cbro@golang.org>
Date:   Thu Feb 16 08:29:46 2017 -0800

    [release-branch.go1.8] doc: document go1.8
    
    Change-Id: Ie2144d001c6b4b2293d07b2acf62d7e3cd0b46a7
    Reviewed-on: https://go-review.googlesource.com/37130
    Reviewed-by: Russ Cox <rsc@golang.org>
    Reviewed-on: https://go-review.googlesource.com/37131

commit bcda91c18d8b4f6ed67897eba2b62a2c21b584a9
Author: Russ Cox <rsc@golang.org>
Date:   Wed Feb 15 15:41:50 2017 -0500

    [release-branch.go1.8] runtime: do not call wakep from enlistWorker, to avoid possible deadlock
    
    We have seen one instance of a production job suddenly spinning to
    100% CPU and becoming unresponsive. In that one instance, a SIGQUIT
    was sent after 328 minutes of spinning, and the stacks showed a single
    goroutine in "IO wait (scan)" state.
    
    Looking for things that might get stuck if a goroutine got stuck in
    scanning a stack, we found that injectglist does:
    
            lock(&sched.lock)
            var n int
            for n = 0; glist != nil; n++ {
                    gp := glist
                    glist = gp.schedlink.ptr()
                    casgstatus(gp, _Gwaiting, _Grunnable)
                    globrunqput(gp)
            }
            unlock(&sched.lock)
    
    and that casgstatus spins on gp.atomicstatus until the _Gscan bit goes
    away. Essentially, this code locks sched.lock and then while holding
    sched.lock, waits to lock gp.atomicstatus.
    
    The code that is doing the scan is:
    
            if castogscanstatus(gp, s, s|_Gscan) {
                    if !gp.gcscandone {
                            scanstack(gp, gcw)
                            gp.gcscandone = true
                    }
                    restartg(gp)
                    break loop
            }
    
    More analysis showed that scanstack can, in a rare case, end up
    calling back into code that acquires sched.lock. For example:
    
            runtime.scanstack at proc.go:866
            calls runtime.gentraceback at mgcmark.go:842
            calls runtime.scanstack$1 at traceback.go:378
            calls runtime.scanframeworker at mgcmark.go:819
            calls runtime.scanblock at mgcmark.go:904
            calls runtime.greyobject at mgcmark.go:1221
            calls (*runtime.gcWork).put at mgcmark.go:1412
            calls (*runtime.gcControllerState).enlistWorker at mgcwork.go:127
            calls runtime.wakep at mgc.go:632
            calls runtime.startm at proc.go:1779
            acquires runtime.sched.lock at proc.go:1675
    
    This path was found with an automated deadlock-detecting tool.
    There are many such paths but they all go through enlistWorker -> wakep.
    
    The evidence strongly suggests that one of these paths is what caused
    the deadlock we observed. We're running those jobs with
    GOTRACEBACK=crash now to try to get more information if it happens
    again.
    
    Further refinement and analysis shows that if we drop the wakep call
    from enlistWorker, the remaining few deadlock cycles found by the tool
    are all false positives caused by not understanding the effect of calls
    to func variables.
    
    The enlistWorker -> wakep call was intended only as a performance
    optimization, it rarely executes, and if it does execute at just the
    wrong time it can (and plausibly did) cause the deadlock we saw.
    
    Comment it out, to avoid the potential deadlock.
    
    Fixes #19112.
    Unfixes #14179.
    
    Change-Id: I6f7e10b890b991c11e79fab7aeefaf70b5d5a07b
    Reviewed-on: https://go-review.googlesource.com/37093
    Run-TryBot: Russ Cox <rsc@golang.org>
    Reviewed-by: Austin Clements <austin@google.com>
    Reviewed-on: https://go-review.googlesource.com/37022
    TryBot-Result: Gobot Gobot <gobot@golang.org>

commit 7d7a0a9d64b12056d5a73beb8eea2970ee15f88e
Author: Sarah Adams <shadams@google.com>
Date:   Tue Feb 14 15:34:46 2017 -0800

    [release-branch.go1.8] doc: update Code of Conduct wording and scope
    
    This change removes the punitive language and anonymous reporting mechanism
    from the Code of Conduct document. Read on for the rationale.
    
    More than a year has passed since the Go Code of Conduct was introduced.
    In that time, there have been a small number (<30) of reports to the Working Group.
    Some reports we handled well, with positive outcomes for all involved.
    A few reports we handled badly, resulting in hurt feelings and a bad
    experience for all involved.
    
    On reflection, the reports that had positive outcomes were ones where the
    Working Group took the role of advisor/facilitator, listening to complaints and
    providing suggestions and advice to the parties involved.
    The reports that had negative outcomes were ones where the subject of the
    report felt threatened by the Working Group and Code of Conduct.
    
    After some discussion among the Working Group, we saw that we are most
    effective as facilitators, rather than disciplinarians. The various Go spaces
    already have moderators; this change to the CoC acknowledges their authority
    and places the group in a purely advisory role. If an incident is
    reported to the group we may provide information to or make a
    suggestion the moderators, but the Working Group need not (and should not) have
    any authority to take disciplinary action.
    
    In short, we want it to be clear that the Working Group are here to help
    resolve conflict, period.
    
    The second change made here is the removal of the anonymous reporting mechanism.
    To date, the quality of anonymous reports has been low, and with no way to
    reach out to the reporter for more information there is often very little we
    can do in response. Removing this one-way reporting mechanism strengthens the
    message that the Working Group are here to facilitate a constructive dialogue.
    
    Change-Id: Iee52aff5446accd0dae0c937bb3aa89709ad5fb4
    Reviewed-on: https://go-review.googlesource.com/37014
    Reviewed-by: Andrew Gerrand <adg@golang.org>
    Reviewed-by: Russ Cox <rsc@golang.org>
    Reviewed-on: https://go-review.googlesource.com/37040
    Reviewed-by: Chris Broadfoot <cbro@golang.org>

commit cedc511a6e71f1ac12835da3bb08b96e1dd69b2e
Author: Russ Cox <rsc@golang.org>
Date:   Tue Feb 14 00:17:50 2017 -0500

    [release-branch.go1.8] encoding/xml: fix incorrect indirect code in chardata, comment, innerxml fields
    
    The new tests in this CL have been checked against Go 1.7 as well
    and all pass in Go 1.7, with the one exception noted in a comment
    (an intentional change to omitempty already present before this CL).
    
    CL 15684 made the intentional change to omitempty.
    This CL fixes bugs introduced along the way.
    
    Most of these are corner cases that are arguably not that important,
    but they've always worked all the way back to Go 1, and someone
    cared enough to file #19063. The most significant problem found
    while adding tests is that in the case of a nil *string field with
    `xml:",chardata"`, the existing code silently stops processing not just
    that field but the entire remainder of the struct.
    Even if #19063 were not worth fixing, this chardata bug would be.
    
    Fixes #19063.
    
    Change-Id: I318cf8f9945e1a4615982d9904e109fde577ebf9
    Reviewed-on: https://go-review.googlesource.com/36954
    Run-TryBot: Russ Cox <rsc@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
    (cherry picked from commit 72aa757dddad7e915f4faad87aacf8010d91561b)
    Reviewed-on: https://go-review.googlesource.com/37016
    Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
    Reviewed-by: Ian Lance Taylor <iant@golang.org>
    Reviewed-by: Russ Cox <rsc@golang.org>

commit ae13ccfd6dee7113d11aba0c1c287bfa2897488d
Author: Daniel Theophanes <kardianos@gmail.com>
Date:   Sun Feb 12 15:12:52 2017 -0800

    [release-branch.go1.8] database/sql: convert test timeouts to explicit waits with checks
    
    When testing context cancelation behavior do not rely on context
    timeouts. Use explicit checks in all such tests. In closeDB
    convert the simple check for zero open conns with a wait loop
    for zero open conns.
    
    Fixes #19024
    Fixes #19041
    
    Change-Id: Iecfcc4467e91249fceb21ffd1f7c62c58140d8e9
    Reviewed-on: https://go-review.googlesource.com/36902
    Run-TryBot: Daniel Theophanes <kardianos@gmail.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Russ Cox <rsc@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36917
    Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
    Reviewed-by: Daniel Theophanes <kardianos@gmail.com>

commit 7cec9a583d81a3b518795cc2a49cd6296e45c69b
Author: Michael Hudson-Doyle <michael.hudson@canonical.com>
Date:   Fri Feb 10 13:08:13 2017 +1300

    [release-branch.go1.8] reflect: clear ptrToThis in Ptr when allocating result on heap
    
    Otherwise, calling PtrTo on the result will fail.
    
    Fixes #19003
    
    Change-Id: I8d7d1981a5d0417d5aee52740469d71e90734963
    Reviewed-on: https://go-review.googlesource.com/36731
    Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Ian Lance Taylor <iant@golang.org>
    Reviewed-by: Russ Cox <rsc@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36718
    Run-TryBot: Russ Cox <rsc@golang.org>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit d84dee069a534bd7a35ec4062a92a04ce9c2806e
Author: Daniel Theophanes <kardianos@gmail.com>
Date:   Wed Feb 8 21:38:51 2017 -0800

    [release-branch.go1.8] database/sql: ensure driverConns are closed if not returned to pool
    
    Previously if a connection was requested but timed out during the
    request and when acquiring the db.Lock the connection request
    is fulfilled and the request is unable to be returned to the
    connection pool, then then driver connection would not be closed.
    
    No tests were added or modified because I was unable to determine
    how to trigger this situation without something invasive.
    
    Change-Id: I9d4dc680e3fdcf63d79d212174a5b8b313f363f1
    Reviewed-on: https://go-review.googlesource.com/36641
    Reviewed-by: Russ Cox <rsc@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36714
    Run-TryBot: Russ Cox <rsc@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit f1e44a4b7426e03bff7ed4f75a91e57c498d3463
Author: Daniel Theophanes <kardianos@gmail.com>
Date:   Wed Feb 8 10:32:22 2017 -0800

    [release-branch.go1.8] database/sql: do not exhaust connection pool on conn request timeout
    
    Previously if a context was canceled while it was waiting for a
    connection request, that connection request would leak.
    
    To prevent this remove the pending connection request if the
    context is canceled and ensure no connection has been sent on the channel.
    This requires a change to how the connection requests are represented in the DB.
    
    Fixes #18995
    
    Change-Id: I9a274b48b8f4f7ca46cdee166faa38f56d030852
    Reviewed-on: https://go-review.googlesource.com/36563
    Reviewed-by: Russ Cox <rsc@golang.org>
    Run-TryBot: Russ Cox <rsc@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36613
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 3ade54063e9a219e50e53a6a042013e2cafc1251
Author: Daniel Theophanes <kardianos@gmail.com>
Date:   Tue Feb 7 10:19:02 2017 -0800

    [release-branch.go1.8] database/sql: record the context error in Rows if canceled
    
    Previously it was intended that Rows.Scan would return
    an error and Rows.Err would return nil. This was problematic
    because drivers could not differentiate between a normal
    Rows.Close or a context cancel close.
    
    The alternative is to require drivers to return a Scan to return
    an error if the driver is closed while there are still rows to be read.
    This is currently not how several drivers currently work and may be
    difficult to detect when there are additional rows.
    
    At the same time guard the the Rows.lasterr and prevent a close
    while a Rows operation is active.
    
    For the drivers that do not have Context methods, do not check for
    context cancelation after the operation, but before for any operation
    that may modify the database state.
    
    Fixes #18961
    
    Change-Id: I49a25318ecd9f97a35d5b50540ecd850c01cfa5e
    Reviewed-on: https://go-review.googlesource.com/36485
    Reviewed-by: Russ Cox <rsc@golang.org>
    Run-TryBot: Russ Cox <rsc@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36614
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 0545006bdb052b3d3fdd14cd027993d89eef1eed
Author: Russ Cox <rsc@golang.org>
Date:   Tue Feb 7 11:59:38 2017 -0500

    [release-branch.go1.8] crypto/x509: check for new tls-ca-bundle.pem last
    
    We added CentOS 7's /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
    to the list in response to #17549 - not being able to find any certs otherwise.
    
    Now we have #18813, where CentOS 6 apparently has both that file
    and /etc/pki/tls/certs/ca-bundle.crt, and the latter is complete while
    the former is not.
    
    Moving the new CentOS 7 file to the bottom of the list should fix both
    problems: the CentOS 7 system that didn't have any of the other files
    in the list will still find the new one, and existing systems will still
    keep using what they were using instead of preferring the new path
    that may or may not be complete on some systems.
    
    Fixes #18813.
    
    Change-Id: I5275ab67424b95e7210e14938d3e986c8caee0ba
    Reviewed-on: https://go-review.googlesource.com/36429
    Run-TryBot: Russ Cox <rsc@golang.org>
    Reviewed-by: Adam Langley <agl@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36530
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 1363eeba6589fca217e155c829b2a7c00bc32a92
Author: Russ Cox <rsc@golang.org>
Date:   Tue Feb 7 10:29:32 2017 -0500

    [release-branch.go1.8] cmd/go, go/build: better defenses against GOPATH=GOROOT
    
    Fixes #18863.
    
    Change-Id: I0723563cd23728b0d43ebcc25979bf8d21e2a72c
    Reviewed-on: https://go-review.googlesource.com/36427
    Run-TryBot: Russ Cox <rsc@golang.org>
    Reviewed-by: Ian Lance Taylor <iant@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36536
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>

commit 1edfd647618afadfeda029372ce169f42821e156
Author: Cherry Zhang <cherryyz@google.com>
Date:   Mon Feb 6 14:24:16 2017 -0500

    [release-branch.go1.8] cmd/compile: do not use "oaslit" for global
    
    The compiler did not emit write barrier for assigning global with
    struct literal, like global = T{} where T contains pointer.
    
    The relevant code path is:
    walkexpr OAS var_ OSTRUCTLIT
        oaslit
            anylit OSTRUCTLIT
                walkexpr OAS var_ nil
                return without adding write barrier
        return true
    break (without adding write barrier)
    
    This CL makes oaslit not apply to globals. See also CL
    https://go-review.googlesource.com/c/36355/ for an alternative
    fix.
    
    The downside of this is that it generates static data for zeroing
    struct now. Also this only covers global. If there is any lurking
    bug with implicit zeroing other than globals, this doesn't fix.
    
    Fixes #18956.
    
    Change-Id: Ibcd27e4fae3aa38390ffa94a32a9dd7a802e4b37
    Reviewed-on: https://go-review.googlesource.com/36410
    Reviewed-by: Russ Cox <rsc@golang.org>
    Run-TryBot: Cherry Zhang <cherryyz@google.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    (cherry picked from commit 160914e33ca6521d74297291d801062cc44d794d)
    Reviewed-on: https://go-review.googlesource.com/36531

commit 6eb0f5440e7034235544001faa675a0945a1ba7b
Author: Robert Griesemer <gri@golang.org>
Date:   Mon Feb 6 22:01:07 2017 -0800

    [release-branch.go1.8] cmd/compile/internal/syntax: avoid follow-up error for incorrect if statement
    
    This is a follow-up on https://go-review.googlesource.com/36470
    and leads to a more stable fix. The above CL relied on filtering
    of multiple errors on the same line to avoid more than one error
    for an `if` statement of the form `if a := 10 {}`. This CL avoids
    the secondary error ("missing condition in if statement") in the
    first place.
    
    For #18915.
    
    Change-Id: I8517f485cc2305965276c17d8f8797d61ef9e999
    Reviewed-on: https://go-review.googlesource.com/36479
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Matthew Dempsky <mdempsky@google.com>
    Reviewed-on: https://go-review.googlesource.com/36424
    Run-TryBot: Russ Cox <rsc@golang.org>
    Reviewed-by: Robert Griesemer <gri@golang.org>

commit c543cc353deb4cffe213be5b094c8357faecab07
Author: Robert Griesemer <gri@golang.org>
Date:   Mon Feb 6 15:08:28 2017 -0800

    [release-branch.go1.8] cmd/compile/internal/syntax: make a parser error "1.7 compliant"
    
    For code such as
    
            if a := 10 { ...
    
    the 1.7 compiler reported
    
            a := 10 used as value
    
    while the 1.8 compiler reported
    
            invalid condition, tag, or type switch guard
    
    Changed the error message to match the 1.7 compiler.
    
    Fixes #18915.
    
    Change-Id: I01308862e461922e717f9f8295a9db53d5a914eb
    Reviewed-on: https://go-review.googlesource.com/36470
    Run-TryBot: Robert Griesemer <gri@golang.org>
    Reviewed-by: Matthew Dempsky <mdempsky@google.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36422
    Run-TryBot: Russ Cox <rsc@golang.org>
    Reviewed-by: Robert Griesemer <gri@golang.org>

commit f0749fe163ca4917f903ed424008af37e834ace4
Author: David Crawshaw <crawshaw@golang.org>
Date:   Mon Feb 6 17:52:26 2017 -0500

    [release-branch.go1.8] cmd/link: use external linking for PIE by default
    
    Now `go test -buildmode=pie std -short` passes on linux/amd64.
    
    Updates #18968
    
    Change-Id: Ide21877713e00edc64c1700c950016d6bff8de0e
    Reviewed-on: https://go-review.googlesource.com/36417
    Reviewed-by: Ian Lance Taylor <iant@golang.org>
    Run-TryBot: Ian Lance Taylor <iant@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36421
    Run-TryBot: Russ Cox <rsc@golang.org>
    Reviewed-by: David Crawshaw <crawshaw@golang.org>
    Reviewed-by: Minux Ma <minux@golang.org>

commit ba878ac0c8ac9701f0171a602cf344accf67c99b
Author: Andrew Gerrand <adg@golang.org>
Date:   Tue Feb 7 08:05:01 2017 +1100

    [release-branch.go1.8] doc: remove inactive members of the CoC working group
    
    Dave and Jason have moved on to other things.
    
    Change-Id: I702d11bedfab1f47a33679a48c2309f49021229e
    Reviewed-on: https://go-review.googlesource.com/36450
    Reviewed-by: Dave Cheney <dave@cheney.net>
    Reviewed-on: https://go-review.googlesource.com/36474
    Reviewed-by: Andrew Gerrand <adg@golang.org>

commit 6177f6d448ffc73d54e28e3827da818f07fc2aa3
Author: Russ Cox <rsc@golang.org>
Date:   Mon Feb 6 14:41:12 2017 -0500

    [release-branch.go1.8] vendor/golang.org/x/crypto/curve25519: avoid loss of R15 in -dynlink mode
    
    Original code fixed in https://go-review.googlesource.com/#/c/36359/.
    
    Fixes #18820.
    
    Change-Id: I060e6c9d0e312b4fd5d0674aff131055bf5cf61d
    Reviewed-on: https://go-review.googlesource.com/36412
    Run-TryBot: Russ Cox <rsc@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Adam Langley <agl@golang.org>
    Reviewed-on: https://go-review.googlesource.com/36414
    Reviewed-by: Austin Clements <austin@google.com>

commit 67cd1fa780aba6ca76e6f43092a2fb80e170dc93
Author: Cherry Zhang <cherryyz@google.com>
Date:   Mon Feb 6 15:05:41 2017 -0500

    [release-branch.go1.8] cmd/compile: do not fold large offset on ARM64
    
    Fixes #18933.
    
    Change-Id: I1ab524fdca006100ec6af572065b496f68d6a5c3
    Reviewed-on: https://go-review.googlesource.com/36413
    Run-TryBot: Cherry Zhang <cherryyz@google.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 758a7281abb539018d6458ccb429615206fcc002
Author: Michael Munday <munday@ca.ibm.com>
Date:   Fri Feb 3 16:47:32 2017 -0500

    [release-branch.go1.8] cmd/compile: fix type propagation through s390x SSA rules
    
    This CL fixes two issues:
    
    1. Load ops were initially always lowered to unsigned loads, even
       for signed types. This was fine by itself however LoadReg ops
       (used to re-load spilled values) were lowered to signed loads
       for signed types. This meant that spills could invalidate
       optimizations that assumed the original unsigned load.
    
    2. Types were not always being maintained correctly through rules
       designed to eliminate unnecessary zero and sign extensions.
    
    Updates #18906 and fixes #18958 (backport of CL 36256 to 1.8).
    
    Change-Id: Id44953b0f644cad047e8474edbd24e8a344ca9a7
    Reviewed-on: https://go-review.googlesource.com/36350
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 470704531d93d1bcc24493abea882f99593bcac6
Author: Alberto Donizetti <alb.donizetti@gmail.com>
Date:   Sun Jan 29 20:53:35 2017 +0100

    [release-branch.go1.8] testing: stop timeout-timer after running tests
    
    Fixes #18845
    
    Fixes #18870 (Go 1.8 backport)
    
    Change-Id: Icdc3e2067807781e42f2ffc94d1824aed94d3713
    Reviewed-on: https://go-review.googlesource.com/35956
    Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Ian Lance Taylor <iant@golang.org>
    (cherry picked from commit 7d8bfdde453445affb50fcaeacc050938ec98467)
    Reviewed-on: https://go-review.googlesource.com/36125

commit 648bb34484e177067b1fc4aa159cd08f9ad2bbf7
Author: Filippo Valsorda <hi@filippo.io>
Date:   Wed Feb 1 19:57:11 2017 +0000

    [release-branch.go1.8] doc: mention SHA-256 CBC suites are off by default
    
    Change-Id: I82c41bd1d82adda457ddb5dd08caf0647905da22
    Reviewed-on: https://go-review.googlesource.com/36091
    Reviewed-by: Matt Layher <mdlayher@gmail.com>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
    (cherry picked from commit de479267ef9db0911dac68e94d75186313bae11d)
    Reviewed-on: https://go-review.googlesource.com/36130

commit d8d2f036a59d887ccd5f7c17bb589bb7c99084cf
Merge: 2a5f65a98c 3e55059f30
Author: Russ Cox <rsc@golang.org>
Date:   Mon Jan 30 16:55:52 2017 -0500

    [release-branch.go1.8] all: final merge of master into Go 1.8 release branch
    
    After this, we will merge some of the dev work like
    type aliases and inlining into master, so any additional
    changes for the Go 1.8 release will need to be cherry-picked,
    not merged.
    
    3e55059f cmd/dist: really skip the testsanitizers tests on Android
    09496599 runtime: add explicit (void) in C to avoid GCC 7 problem
    4cffe2b6 cmd/dist: use the target GOOS to skip the test for issue 18153
    6bdb0c11 doc: update go1.8 release notes after TxOptions change
    09096bd3 cmd/go: update alldocs after CL 35150
    96ea0918 cmd/compile: use CMPWU for 32-bit or smaller unsigned Geq on ppc64{,le}
    21a8db1c doc: document go1.7.5
    
    Change-Id: I9e6a30c3fac43d4d4d15e93054ac00964c3ee958

commit 3e55059f305bde37a4dac1397e8a1b798b6fbd9e
Author: Elias Naur <elias.naur@gmail.com>
Date:   Mon Jan 30 19:55:35 2017 +0100

    cmd/dist: really skip the testsanitizers tests on Android
    
    The test.bash script in misc/cgo/testsanitizers use GOOS, not GOHOSTOS.
    Fix the dist check from gohostos to goos accordingly.
    
    The error was masked on the builders because they run on a darwin host
    where the sanitizers tests never ran.
    
    With this change, the Android test suite completes successfully on
    Android/amd64.
    
    Change-Id: Id7690429f78c6ac7a26fc9118d913b719b565bb2
    Reviewed-on: https://go-review.googlesource.com/35959
    Reviewed-by: Ian Lance Taylor <iant@golang.org>
    Run-TryBot: Elias Naur <elias.naur@gmail.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>

commit 09496599520d73171550987b138d85ae1fb13b76
Author: Ian Lance Taylor <iant@golang.org>
Date:   Mon Jan 30 09:43:25 2017 -0800

    runtime: add explicit (void) in C to avoid GCC 7 problem
    
    This avoids errors like
        ./traceback.go:80:2: call of non-function C.f1
    
    I filed https://gcc.gnu.org/PR79289 for the GCC problem. I think this
    is a bug in GCC, and it may be fixed before the final GCC 7 release.
    This CL is correct either way.
    
    Fixes #18855.
    
    Change-Id: I0785a7b7c5b1d0ca87b454b5eca9079f390fcbd4
    Reviewed-on: https://go-review.googlesource.com/35919
    Run-TryBot: Ian Lance Taylor <iant@golang.org>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: David Crawshaw <crawshaw@golang.org>

commit 4cffe2b604d0980e6fb9b994b31f69c53045a460
Author: Elias Naur <elias.naur@gmail.com>
Date:   Sun Jan 29 23:57:14 2017 +0100

    cmd/dist: use the target GOOS to skip the test for issue 18153
    
    Fixes (skips) the test on Android, where stdout/stderr are not
    terminals.
    
    Updates #18153
    
    Change-Id: Ieca65150362a5c423747ad751e00f76f0b890746
    Reviewed-on: https://go-review.googlesource.com/35957
    Run-TryBot: Elias Naur <elias.naur@gmail.com>
    TryBot-Result: Gobot Gobot <gobot@golang.org>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 6bdb0c11c73ecf2337918d784c54f9dda2207ca7
Author: Daniel Theophanes <kardianos@gmail.com>
Date:   Sat Jan 28 07:36:09 2017 -0800

    doc: update go1.8 release notes after TxOptions change
    
    Missed the release notes when updating the sql API.
    
    Fixes #18825
    
    Change-Id: I89056d46939ad4fc99590f3434d2881f5764e1b6
    Reviewed-on: https://go-review.googlesource.com/35915
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 09096bd3eb59af83796066f517301bb51ad25d4e
Author: Alberto Donizetti <alb.donizetti@gmail.com>
Date:   Sat Jan 28 11:56:15 2017 +0100

    cmd/go: update alldocs after CL 35150
    
    Author of CL 35150 forgot to run mkalldocs.sh to update
    the autogenerated alldocs.go
    
    Change-Id: Ib824562db6044702456a221a8c6f9af412927a98
    Reviewed-on: https://go-review.googlesource.com/35952
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>

commit 96ea0918e6708d3548215ade59dc4f89bc814e6b
Author: Michael Munday <munday@ca.ibm.com>
Date:   Thu Jan 26 23:31:28 2017 -0500

    cmd/compile: use CMPWU for 32-bit or smaller unsigned Geq on ppc64{,le}
    
    Fixes #18808.
    
    Change-Id: I49b266380b9d6804c9f6563ebac9c7c0e05f37f6
    Reviewed-on: https://go-review.googlesource.com/35890
    Run-TryBot: Michael Munday <munday@ca.ibm.com>
    Reviewed-by: Cherry Zhang <cherryyz@google.com>

commit 21a8db1c5fdd372510b30bb898269a56456096e8
Author: Chris Broadfoot <cbro@golang.org>
Date:   Thu Jan 26 09:30:04 2017 -0800

    doc: document go1.7.5
    
    Change-Id: Ic8d4e971edebba9412f2e7c3d3c29f296c4977ff
    Reviewed-on: https://go-review.googlesource.com/35833
    Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
    Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff -Nru golang-1.8-1.8~rc3/debian/changelog golang-1.8-1.8.1/debian/changelog
--- golang-1.8-1.8~rc3/debian/changelog	2017-01-26 22:23:56.000000000 +0100
+++ golang-1.8-1.8.1/debian/changelog	2017-04-10 03:29:32.000000000 +0200
@@ -1,3 +1,15 @@
+golang-1.8 (1.8.1-1) unstable; urgency=medium
+
+  * New upstream release.
+
+ -- Michael Hudson-Doyle <michael.hudson@ubuntu.com>  Mon, 10 Apr 2017 13:29:28 +1200
+
+golang-1.8 (1.8-1) unstable; urgency=medium
+
+  * New upstream release.
+
+ -- Michael Hudson-Doyle <michael.hudson@ubuntu.com>  Thu, 02 Mar 2017 10:11:55 +1300
+
 golang-1.8 (1.8~rc3-1) unstable; urgency=medium
 
   * New upstream release.
diff -Nru golang-1.8-1.8~rc3/doc/conduct.html golang-1.8-1.8.1/doc/conduct.html
--- golang-1.8-1.8~rc3/doc/conduct.html	2017-01-26 19:54:56.000000000 +0100
+++ golang-1.8-1.8.1/doc/conduct.html	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/doc/contrib.html golang-1.8-1.8.1/doc/contrib.html
--- golang-1.8-1.8~rc3/doc/contrib.html	2017-01-26 19:54:56.000000000 +0100
+++ golang-1.8-1.8.1/doc/contrib.html	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/doc/contribute.html golang-1.8-1.8.1/doc/contribute.html
--- golang-1.8-1.8~rc3/doc/contribute.html	2017-01-26 19:54:56.000000000 +0100
+++ golang-1.8-1.8.1/doc/contribute.html	2017-04-07 18:54:08.000000000 +0200
@@ -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>
-
-<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 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>
+<h1 id="contributor">Becoming a contributor</h1>
 
 <p>
-(To build under Windows use <code>all.bat</code>.)
+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>
-After running for a while, the command should print
-"<code>ALL</code> <code>TESTS</code> <code>PASSED</code>".
+You'll need a web browser and a command line terminal.
+You should already have Git installed.
 </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.
+You will be redirected to accounts.google.com to sign in.
 </p>
 
+<h3>Step 2: Run the provided script</h3>
 <p>
-You will be redirected to accounts.google.com to sign in.
+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>
-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.)
+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>
+
+<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>
 
-<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:
 <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>
+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>
 <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.
+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>
+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>
+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>
-The entire checked-out tree is writable.
 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,35 +525,44 @@
 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>
-$ git mail
+$ cd go/src
+$ ./all.bash
 </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:
+(To build under Windows use <code>all.bat</code>.)
+</p>
+
+<p>
+After running for a while, the command should print
 </p>
 
 <pre>
-$ git mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com
+"ALL TESTS PASSED".
 </pre>
 
+<h3 id="mail">Send the change for review</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.
+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>
+$ git mail
+</pre>
+
 <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>
@@ -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 -Nru golang-1.8-1.8~rc3/doc/devel/release.html golang-1.8-1.8.1/doc/devel/release.html
--- golang-1.8-1.8~rc3/doc/devel/release.html	2017-01-26 19:54:56.000000000 +0100
+++ golang-1.8-1.8.1/doc/devel/release.html	2017-04-07 18:54:08.000000000 +0200
@@ -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>
@@ -69,6 +88,13 @@
 1.7.4 milestone</a> on our issue tracker for details.
 </p>
 
+<p>
+go1.7.5 (released 2017/01/26) includes fixes to the compiler, runtime,
+and the <code>crypto/x509</code> and <code>time</code> packages.
+See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.5";>Go
+1.7.5 milestone</a> on our issue tracker for details.
+</p>
+
 <h2 id="go1.6">go1.6 (released 2016/02/17)</h2>
 
 <p>
diff -Nru golang-1.8-1.8~rc3/doc/go1.8.html golang-1.8-1.8.1/doc/go1.8.html
--- golang-1.8-1.8~rc3/doc/go1.8.html	2017-01-26 19:54:56.000000000 +0100
+++ golang-1.8-1.8.1/doc/go1.8.html	2017-04-07 18:54:08.000000000 +0200
@@ -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>.
@@ -799,9 +794,9 @@
       hardware support for AES-GCM is present.
     </p>
 
-    <p> <!-- CL 27315 -->
+    <p> <!-- CL 27315, CL 35290 -->
       AES-128-CBC cipher suites with SHA-256 are also
-      now supported.
+      now supported, but disabled by default.
     </p>
 
   </dd>
@@ -859,11 +854,12 @@
     <p>
       The <a href="/pkg/database/sql#IsolationLevel"><code>IsolationLevel</code></a>
       can now be set when starting a transaction by setting the isolation level
-      on the <code>Context</code> then passing that <code>Context</code> to
-      <a href="/pkg/database/sql#DB.BeginContext"><code>DB.BeginContext</code></a>.
+      on <a href="/pkg/database/sql#TxOptions.Isolation"><code>TxOptions.Isolation</code></a> and passing
+      it to <a href="/pkg/database/sql#DB.BeginTx"><code>DB.BeginTx</code></a>.
       An error will be returned if an isolation level is selected that the driver
       does not support. A read-only attribute may also be set on the transaction
-      with <a href="/pkg/database/sql/#ReadOnlyContext"><code>ReadOnlyContext</code></a>.
+      by setting <a href="/pkg/database/sql/#TxOptions.ReadOnly"><code>TxOptions.ReadOnly</code></a>
+      to true.
     </p>
     <p>
       Queries now expose the SQL column type information for drivers that support it.
@@ -1308,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 -Nru golang-1.8-1.8~rc3/doc/install-source.html golang-1.8-1.8.1/doc/install-source.html
--- golang-1.8-1.8~rc3/doc/install-source.html	2017-01-26 19:54:56.000000000 +0100
+++ golang-1.8-1.8.1/doc/install-source.html	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/misc/cgo/testcshared/test.bash golang-1.8-1.8.1/misc/cgo/testcshared/test.bash
--- golang-1.8-1.8~rc3/misc/cgo/testcshared/test.bash	2017-01-26 19:54:56.000000000 +0100
+++ golang-1.8-1.8.1/misc/cgo/testcshared/test.bash	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/esc.go golang-1.8-1.8.1/src/cmd/compile/internal/gc/esc.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/esc.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/gc/esc.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/sinit.go golang-1.8-1.8.1/src/cmd/compile/internal/gc/sinit.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/sinit.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/gc/sinit.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/ssa.go golang-1.8-1.8.1/src/cmd/compile/internal/gc/ssa.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/ssa.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/gc/ssa.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/testdata/arith.go golang-1.8-1.8.1/src/cmd/compile/internal/gc/testdata/arith.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/testdata/arith.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/gc/testdata/arith.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/typecheck.go golang-1.8-1.8.1/src/cmd/compile/internal/gc/typecheck.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/typecheck.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/gc/typecheck.go	2017-04-07 18:54:08.000000000 +0200
@@ -1107,7 +1107,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)
@@ -1119,6 +1119,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)
@@ -1131,12 +1135,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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/walk.go golang-1.8-1.8.1/src/cmd/compile/internal/gc/walk.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/gc/walk.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/gc/walk.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/s390x/ssa.go golang-1.8-1.8.1/src/cmd/compile/internal/s390x/ssa.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/s390x/ssa.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/s390x/ssa.go	2017-04-07 18:54:08.000000000 +0200
@@ -424,7 +424,7 @@
 		p.To.Type = obj.TYPE_MEM
 		p.To.Reg = v.Args[0].Reg()
 		gc.AddAux2(&p.To, v, sc.Off())
-	case ssa.OpCopy, ssa.OpS390XMOVDconvert:
+	case ssa.OpCopy, ssa.OpS390XMOVDconvert, ssa.OpS390XMOVDreg:
 		if v.Type.IsMemory() {
 			return
 		}
@@ -433,6 +433,11 @@
 		if x != y {
 			opregreg(moveByType(v.Type), y, x)
 		}
+	case ssa.OpS390XMOVDnop:
+		if v.Reg() != v.Args[0].Reg() {
+			v.Fatalf("input[0] and output not in same register %s", v.LongString())
+		}
+		// nothing to do
 	case ssa.OpLoadReg:
 		if v.Type.IsFlags() {
 			v.Fatalf("load flags not implemented: %v", v.LongString())
diff -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/deadcode.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/deadcode.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/deadcode.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/deadcode.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/export_test.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/export_test.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/export_test.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/export_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/AMD64Ops.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/AMD64Ops.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/AMD64Ops.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/AMD64Ops.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/ARM64Ops.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/ARM64Ops.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/ARM64Ops.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/ARM64Ops.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/ARM64.rules golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/ARM64.rules
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/ARM64.rules	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/ARM64.rules	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/ARMOps.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/ARMOps.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/ARMOps.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/ARMOps.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/ARM.rules golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/ARM.rules
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/ARM.rules	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/ARM.rules	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/genericOps.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/genericOps.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/genericOps.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/genericOps.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/main.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/main.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/main.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/main.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/MIPSOps.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/MIPSOps.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/MIPSOps.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/MIPSOps.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/MIPS.rules golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/MIPS.rules
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/MIPS.rules	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/MIPS.rules	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/PPC64.rules golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/PPC64.rules
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/PPC64.rules	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/PPC64.rules	2017-04-07 18:54:08.000000000 +0200
@@ -338,9 +338,9 @@
 (Geq32F x y) -> (FGreaterEqual (FCMPU x y))
 (Geq64F x y) -> (FGreaterEqual (FCMPU x y))
 
-(Geq8U x y)  -> (GreaterEqual (CMPU (ZeroExt8to32 x) (ZeroExt8to32 y)))
-(Geq16U x y) -> (GreaterEqual (CMPU (ZeroExt16to32 x) (ZeroExt16to32 y)))
-(Geq32U x y) -> (GreaterEqual (CMPU x y))
+(Geq8U x y)  -> (GreaterEqual (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+(Geq16U x y) -> (GreaterEqual (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+(Geq32U x y) -> (GreaterEqual (CMPWU x y))
 (Geq64U x y) -> (GreaterEqual (CMPU x y))
 
 // Absorb pseudo-ops into blocks.
diff -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/S390XOps.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/S390XOps.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/S390XOps.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/S390XOps.go	2017-04-07 18:54:08.000000000 +0200
@@ -311,6 +311,9 @@
 		{name: "MOVHZreg", argLength: 1, reg: gp11sp, asm: "MOVHZ", typ: "UInt64"}, // zero extend arg0 from int16 to int64
 		{name: "MOVWreg", argLength: 1, reg: gp11sp, asm: "MOVW", typ: "Int64"},    // sign extend arg0 from int32 to int64
 		{name: "MOVWZreg", argLength: 1, reg: gp11sp, asm: "MOVWZ", typ: "UInt64"}, // zero extend arg0 from int32 to int64
+		{name: "MOVDreg", argLength: 1, reg: gp11sp, asm: "MOVD"},                  // move from arg0
+
+		{name: "MOVDnop", argLength: 1, reg: gp11, resultInArg0: true}, // nop, return arg0 in same register
 
 		{name: "MOVDconst", reg: gp01, asm: "MOVD", typ: "UInt64", aux: "Int64", rematerializeable: true}, // auxint
 
@@ -426,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>.
 
@@ -458,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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/S390X.rules golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/S390X.rules
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/gen/S390X.rules	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/gen/S390X.rules	2017-04-07 18:54:08.000000000 +0200
@@ -312,9 +312,12 @@
 
 // Lowering loads
 (Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload ptr mem)
-(Load <t> ptr mem) && is32BitInt(t) -> (MOVWZload ptr mem)
-(Load <t> ptr mem) && is16BitInt(t) -> (MOVHZload ptr mem)
-(Load <t> ptr mem) && (t.IsBoolean() || is8BitInt(t)) -> (MOVBZload ptr mem)
+(Load <t> ptr mem) && is32BitInt(t) && isSigned(t) -> (MOVWload ptr mem)
+(Load <t> ptr mem) && is32BitInt(t) && !isSigned(t) -> (MOVWZload ptr mem)
+(Load <t> ptr mem) && is16BitInt(t) && isSigned(t) -> (MOVHload ptr mem)
+(Load <t> ptr mem) && is16BitInt(t) && !isSigned(t) -> (MOVHZload ptr mem)
+(Load <t> ptr mem) && is8BitInt(t) && isSigned(t) -> (MOVBload ptr mem)
+(Load <t> ptr mem) && (t.IsBoolean() || (is8BitInt(t) && !isSigned(t))) -> (MOVBZload ptr mem)
 (Load <t> ptr mem) && is32BitFloat(t) -> (FMOVSload ptr mem)
 (Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem)
 
@@ -437,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
@@ -445,16 +448,28 @@
 // ***************************
 // TODO: Should the optimizations be a separate pass?
 
+// 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)
+
 // Fold sign extensions into conditional moves of constants.
 // Designed to remove the MOVBZreg inserted by the If lowering.
-(MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
-(MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
-(MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
-(MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
-(MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
-(MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
-(MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
-(MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> x
+(MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
+(MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
+(MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
+(MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
+(MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
+(MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
+(MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
+(MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _)) && int64(uint8(c)) == c && int64(uint8(d)) == d -> (MOVDreg x)
 
 // Fold boolean tests into blocks.
 (NE (CMPWconst [0] (MOVDLT (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (LT cmp yes no)
@@ -572,46 +587,46 @@
 (MOVDNE x y (InvertFlags cmp)) -> (MOVDNE x y cmp)
 
 // don't extend after proper load
-(MOVBreg x:(MOVBload _ _)) -> x
-(MOVBZreg x:(MOVBZload _ _)) -> x
-(MOVHreg x:(MOVBload _ _)) -> x
-(MOVHreg x:(MOVBZload _ _)) -> x
-(MOVHreg x:(MOVHload _ _)) -> x
-(MOVHZreg x:(MOVBZload _ _)) -> x
-(MOVHZreg x:(MOVHZload _ _)) -> x
-(MOVWreg x:(MOVBload _ _)) -> x
-(MOVWreg x:(MOVBZload _ _)) -> x
-(MOVWreg x:(MOVHload _ _)) -> x
-(MOVWreg x:(MOVHZload _ _)) -> x
-(MOVWreg x:(MOVWload _ _)) -> x
-(MOVWZreg x:(MOVBZload _ _)) -> x
-(MOVWZreg x:(MOVHZload _ _)) -> x
-(MOVWZreg x:(MOVWZload _ _)) -> x
+(MOVBreg x:(MOVBload _ _)) -> (MOVDreg x)
+(MOVBZreg x:(MOVBZload _ _)) -> (MOVDreg x)
+(MOVHreg x:(MOVBload _ _)) -> (MOVDreg x)
+(MOVHreg x:(MOVBZload _ _)) -> (MOVDreg x)
+(MOVHreg x:(MOVHload _ _)) -> (MOVDreg x)
+(MOVHZreg x:(MOVBZload _ _)) -> (MOVDreg x)
+(MOVHZreg x:(MOVHZload _ _)) -> (MOVDreg x)
+(MOVWreg x:(MOVBload _ _)) -> (MOVDreg x)
+(MOVWreg x:(MOVBZload _ _)) -> (MOVDreg x)
+(MOVWreg x:(MOVHload _ _)) -> (MOVDreg x)
+(MOVWreg x:(MOVHZload _ _)) -> (MOVDreg x)
+(MOVWreg x:(MOVWload _ _)) -> (MOVDreg x)
+(MOVWZreg x:(MOVBZload _ _)) -> (MOVDreg x)
+(MOVWZreg x:(MOVHZload _ _)) -> (MOVDreg x)
+(MOVWZreg x:(MOVWZload _ _)) -> (MOVDreg x)
 
 // don't extend if argument is already extended
-(MOVBreg x:(Arg <t>)) && is8BitInt(t) && isSigned(t) -> x
-(MOVBZreg x:(Arg <t>)) && is8BitInt(t) && !isSigned(t) -> x
-(MOVHreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && isSigned(t) -> x
-(MOVHZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && !isSigned(t) -> x
-(MOVWreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t) -> x
-(MOVWZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t) -> x
+(MOVBreg x:(Arg <t>)) && is8BitInt(t) && isSigned(t) -> (MOVDreg x)
+(MOVBZreg x:(Arg <t>)) && is8BitInt(t) && !isSigned(t) -> (MOVDreg x)
+(MOVHreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && isSigned(t) -> (MOVDreg x)
+(MOVHZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t)) && !isSigned(t) -> (MOVDreg x)
+(MOVWreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t) -> (MOVDreg x)
+(MOVWZreg x:(Arg <t>)) && (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t) -> (MOVDreg x)
 
 // fold double extensions
-(MOVBreg x:(MOVBreg _)) -> x
-(MOVBZreg x:(MOVBZreg _)) -> x
-(MOVHreg x:(MOVBreg _)) -> x
-(MOVHreg x:(MOVBZreg _)) -> x
-(MOVHreg x:(MOVHreg _)) -> x
-(MOVHZreg x:(MOVBZreg _)) -> x
-(MOVHZreg x:(MOVHZreg _)) -> x
-(MOVWreg x:(MOVBreg _)) -> x
-(MOVWreg x:(MOVBZreg _)) -> x
-(MOVWreg x:(MOVHreg _)) -> x
-(MOVWreg x:(MOVHreg _)) -> x
-(MOVWreg x:(MOVWreg _)) -> x
-(MOVWZreg x:(MOVBZreg _)) -> x
-(MOVWZreg x:(MOVHZreg _)) -> x
-(MOVWZreg x:(MOVWZreg _)) -> x
+(MOVBreg x:(MOVBreg _)) -> (MOVDreg x)
+(MOVBZreg x:(MOVBZreg _)) -> (MOVDreg x)
+(MOVHreg x:(MOVBreg _)) -> (MOVDreg x)
+(MOVHreg x:(MOVBZreg _)) -> (MOVDreg x)
+(MOVHreg x:(MOVHreg _)) -> (MOVDreg x)
+(MOVHZreg x:(MOVBZreg _)) -> (MOVDreg x)
+(MOVHZreg x:(MOVHZreg _)) -> (MOVDreg x)
+(MOVWreg x:(MOVBreg _)) -> (MOVDreg x)
+(MOVWreg x:(MOVBZreg _)) -> (MOVDreg x)
+(MOVWreg x:(MOVHreg _)) -> (MOVDreg x)
+(MOVWreg x:(MOVHreg _)) -> (MOVDreg x)
+(MOVWreg x:(MOVWreg _)) -> (MOVDreg x)
+(MOVWZreg x:(MOVBZreg _)) -> (MOVDreg x)
+(MOVWZreg x:(MOVHZreg _)) -> (MOVDreg x)
+(MOVWZreg x:(MOVWZreg _)) -> (MOVDreg x)
 
 // fold extensions into constants
 (MOVBreg (MOVDconst [c])) -> (MOVDconst [int64(int8(c))])
@@ -641,10 +656,10 @@
 (MOVWZreg x:(MOVWZloadidx [off] {sym} ptr idx mem)) && x.Uses == 1 && clobber(x) -> @x.Block (MOVWZloadidx <v.Type> [off] {sym} ptr idx mem)
 
 // replace load from same location as preceding store with copy
-(MOVBZload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
-(MOVHZload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
-(MOVWZload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
-(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> x
+(MOVBZload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
+(MOVHZload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
+(MOVWZload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
+(MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _)) && sym == sym2 && off == off2 && isSamePtr(ptr, ptr2) -> (MOVDreg x)
 
 // Don't extend before storing
 (MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
diff -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/likelyadjust.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/likelyadjust.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/likelyadjust.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/likelyadjust.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/loop_test.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/loop_test.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/loop_test.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/loop_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/opGen.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/opGen.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/opGen.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/opGen.go	2017-04-07 18:54:08.000000000 +0200
@@ -1473,6 +1473,8 @@
 	OpS390XMOVHZreg
 	OpS390XMOVWreg
 	OpS390XMOVWZreg
+	OpS390XMOVDreg
+	OpS390XMOVDnop
 	OpS390XMOVDconst
 	OpS390XCFDBRA
 	OpS390XCGDBRA
@@ -7305,6 +7307,7 @@
 		argLen:         3,
 		resultInArg0:   true,
 		faultOnNilArg1: true,
+		hasSideEffects: true,
 		asm:            x86.AXCHGL,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7322,6 +7325,7 @@
 		argLen:         3,
 		resultInArg0:   true,
 		faultOnNilArg1: true,
+		hasSideEffects: true,
 		asm:            x86.AXCHGQ,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7340,6 +7344,7 @@
 		resultInArg0:   true,
 		clobberFlags:   true,
 		faultOnNilArg1: true,
+		hasSideEffects: true,
 		asm:            x86.AXADDL,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7358,6 +7363,7 @@
 		resultInArg0:   true,
 		clobberFlags:   true,
 		faultOnNilArg1: true,
+		hasSideEffects: true,
 		asm:            x86.AXADDQ,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7385,6 +7391,7 @@
 		argLen:         4,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            x86.ACMPXCHGL,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7405,6 +7412,7 @@
 		argLen:         4,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            x86.ACMPXCHGQ,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7425,6 +7433,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            x86.AANDB,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -7439,6 +7448,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            x86.AORB,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -10073,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
 			},
@@ -10086,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
 			},
@@ -10099,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
 			},
@@ -10112,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
 			},
@@ -10125,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
 			},
@@ -10138,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
 			},
@@ -10151,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
 			},
@@ -10164,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
 			},
@@ -12655,6 +12673,7 @@
 		name:           "STLR",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            arm64.ASTLR,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -12667,6 +12686,7 @@
 		name:           "STLRW",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            arm64.ASTLRW,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -12680,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
@@ -12695,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
@@ -12710,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
@@ -12725,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
@@ -12741,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
@@ -12758,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
@@ -12773,6 +12799,7 @@
 		name:           "LoweredAtomicAnd8",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            arm64.AAND,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -12785,6 +12812,7 @@
 		name:           "LoweredAtomicOr8",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            arm64.AORR,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -13975,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
@@ -13986,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
@@ -13997,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
@@ -14012,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
@@ -14028,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
@@ -14042,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
@@ -14057,6 +14091,7 @@
 		name:           "LoweredAtomicAnd",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            mips.AAND,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -14069,6 +14104,7 @@
 		name:           "LoweredAtomicOr",
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            mips.AOR,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -18571,6 +18607,32 @@
 		},
 	},
 	{
+		name:   "MOVDreg",
+		argLen: 1,
+		asm:    s390x.AMOVD,
+		reg: regInfo{
+			inputs: []inputInfo{
+				{0, 54271}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14 SP
+			},
+			outputs: []outputInfo{
+				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+			},
+		},
+	},
+	{
+		name:         "MOVDnop",
+		argLen:       1,
+		resultInArg0: true,
+		reg: regInfo{
+			inputs: []inputInfo{
+				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+			},
+			outputs: []outputInfo{
+				{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
+			},
+		},
+	},
+	{
 		name:              "MOVDconst",
 		auxType:           auxInt64,
 		argLen:            0,
@@ -19472,6 +19534,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.AMOVW,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19486,6 +19549,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.AMOVD,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19499,6 +19563,7 @@
 		auxType:        auxSymOff,
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ALAA,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19515,6 +19580,7 @@
 		auxType:        auxSymOff,
 		argLen:         3,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ALAAG,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19542,6 +19608,7 @@
 		argLen:         4,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ACS,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19562,6 +19629,7 @@
 		argLen:         4,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ACSG,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19582,6 +19650,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ACS,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -19600,6 +19669,7 @@
 		argLen:         3,
 		clobberFlags:   true,
 		faultOnNilArg0: true,
+		hasSideEffects: true,
 		asm:            s390x.ACSG,
 		reg: regInfo{
 			inputs: []inputInfo{
@@ -21387,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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/op.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/op.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/op.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/op.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewriteARM64.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewriteARM64.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewriteARM64.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewriteARM64.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewriteARM.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewriteARM.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewriteARM.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewriteARM.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewriteMIPS.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewriteMIPS.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewriteMIPS.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewriteMIPS.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewritePPC64.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewritePPC64.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewritePPC64.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewritePPC64.go	2017-04-07 18:54:08.000000000 +0200
@@ -1543,12 +1543,12 @@
 	_ = b
 	// match: (Geq16U x y)
 	// cond:
-	// result: (GreaterEqual (CMPU (ZeroExt16to32 x) (ZeroExt16to32 y)))
+	// result: (GreaterEqual (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
 	for {
 		x := v.Args[0]
 		y := v.Args[1]
 		v.reset(OpPPC64GreaterEqual)
-		v0 := b.NewValue0(v.Line, OpPPC64CMPU, TypeFlags)
+		v0 := b.NewValue0(v.Line, OpPPC64CMPWU, TypeFlags)
 		v1 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
 		v1.AddArg(x)
 		v0.AddArg(v1)
@@ -1598,12 +1598,12 @@
 	_ = b
 	// match: (Geq32U x y)
 	// cond:
-	// result: (GreaterEqual (CMPU x y))
+	// result: (GreaterEqual (CMPWU x y))
 	for {
 		x := v.Args[0]
 		y := v.Args[1]
 		v.reset(OpPPC64GreaterEqual)
-		v0 := b.NewValue0(v.Line, OpPPC64CMPU, TypeFlags)
+		v0 := b.NewValue0(v.Line, OpPPC64CMPWU, TypeFlags)
 		v0.AddArg(x)
 		v0.AddArg(y)
 		v.AddArg(v0)
@@ -1687,12 +1687,12 @@
 	_ = b
 	// match: (Geq8U x y)
 	// cond:
-	// result: (GreaterEqual (CMPU (ZeroExt8to32 x) (ZeroExt8to32 y)))
+	// result: (GreaterEqual (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
 	for {
 		x := v.Args[0]
 		y := v.Args[1]
 		v.reset(OpPPC64GreaterEqual)
-		v0 := b.NewValue0(v.Line, OpPPC64CMPU, TypeFlags)
+		v0 := b.NewValue0(v.Line, OpPPC64CMPWU, TypeFlags)
 		v1 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
 		v1.AddArg(x)
 		v0.AddArg(v1)
diff -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewriteS390X.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewriteS390X.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/rewriteS390X.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/rewriteS390X.go	2017-04-07 18:54:08.000000000 +0200
@@ -524,6 +524,10 @@
 		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:
 		return rewriteValueS390X_OpS390XMOVDstore(v, config)
 	case OpS390XMOVDstoreconst:
@@ -3236,13 +3240,28 @@
 		return true
 	}
 	// match: (Load <t> ptr mem)
-	// cond: is32BitInt(t)
+	// cond: is32BitInt(t) && isSigned(t)
+	// result: (MOVWload ptr mem)
+	for {
+		t := v.Type
+		ptr := v.Args[0]
+		mem := v.Args[1]
+		if !(is32BitInt(t) && isSigned(t)) {
+			break
+		}
+		v.reset(OpS390XMOVWload)
+		v.AddArg(ptr)
+		v.AddArg(mem)
+		return true
+	}
+	// match: (Load <t> ptr mem)
+	// cond: is32BitInt(t) && !isSigned(t)
 	// result: (MOVWZload ptr mem)
 	for {
 		t := v.Type
 		ptr := v.Args[0]
 		mem := v.Args[1]
-		if !(is32BitInt(t)) {
+		if !(is32BitInt(t) && !isSigned(t)) {
 			break
 		}
 		v.reset(OpS390XMOVWZload)
@@ -3251,13 +3270,28 @@
 		return true
 	}
 	// match: (Load <t> ptr mem)
-	// cond: is16BitInt(t)
+	// cond: is16BitInt(t) && isSigned(t)
+	// result: (MOVHload ptr mem)
+	for {
+		t := v.Type
+		ptr := v.Args[0]
+		mem := v.Args[1]
+		if !(is16BitInt(t) && isSigned(t)) {
+			break
+		}
+		v.reset(OpS390XMOVHload)
+		v.AddArg(ptr)
+		v.AddArg(mem)
+		return true
+	}
+	// match: (Load <t> ptr mem)
+	// cond: is16BitInt(t) && !isSigned(t)
 	// result: (MOVHZload ptr mem)
 	for {
 		t := v.Type
 		ptr := v.Args[0]
 		mem := v.Args[1]
-		if !(is16BitInt(t)) {
+		if !(is16BitInt(t) && !isSigned(t)) {
 			break
 		}
 		v.reset(OpS390XMOVHZload)
@@ -3266,13 +3300,28 @@
 		return true
 	}
 	// match: (Load <t> ptr mem)
-	// cond: (t.IsBoolean() || is8BitInt(t))
+	// cond: is8BitInt(t) && isSigned(t)
+	// result: (MOVBload ptr mem)
+	for {
+		t := v.Type
+		ptr := v.Args[0]
+		mem := v.Args[1]
+		if !(is8BitInt(t) && isSigned(t)) {
+			break
+		}
+		v.reset(OpS390XMOVBload)
+		v.AddArg(ptr)
+		v.AddArg(mem)
+		return true
+	}
+	// match: (Load <t> ptr mem)
+	// cond: (t.IsBoolean() || (is8BitInt(t) && !isSigned(t)))
 	// result: (MOVBZload ptr mem)
 	for {
 		t := v.Type
 		ptr := v.Args[0]
 		mem := v.Args[1]
-		if !(t.IsBoolean() || is8BitInt(t)) {
+		if !(t.IsBoolean() || (is8BitInt(t) && !isSigned(t))) {
 			break
 		}
 		v.reset(OpS390XMOVBZload)
@@ -7802,7 +7851,7 @@
 	_ = b
 	// match: (MOVBZload [off] {sym} ptr (MOVBstore [off2] {sym2} ptr2 x _))
 	// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		off := v.AuxInt
 		sym := v.Aux
@@ -7818,8 +7867,7 @@
 		if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -7976,7 +8024,7 @@
 	_ = b
 	// match: (MOVBZreg x:(MOVDLT (MOVDconst [c]) (MOVDconst [d]) _))
 	// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVDLT {
@@ -7995,14 +8043,13 @@
 		if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVDLE (MOVDconst [c]) (MOVDconst [d]) _))
 	// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVDLE {
@@ -8021,14 +8068,13 @@
 		if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVDGT (MOVDconst [c]) (MOVDconst [d]) _))
 	// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVDGT {
@@ -8047,14 +8093,13 @@
 		if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVDGE (MOVDconst [c]) (MOVDconst [d]) _))
 	// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVDGE {
@@ -8073,14 +8118,13 @@
 		if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVDEQ (MOVDconst [c]) (MOVDconst [d]) _))
 	// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVDEQ {
@@ -8099,14 +8143,13 @@
 		if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVDNE (MOVDconst [c]) (MOVDconst [d]) _))
 	// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVDNE {
@@ -8125,14 +8168,13 @@
 		if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVDGTnoinv (MOVDconst [c]) (MOVDconst [d]) _))
 	// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVDGTnoinv {
@@ -8151,14 +8193,13 @@
 		if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVDGEnoinv (MOVDconst [c]) (MOVDconst [d]) _))
 	// cond: int64(uint8(c)) == c && int64(uint8(d)) == d
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVDGEnoinv {
@@ -8177,27 +8218,25 @@
 		if !(int64(uint8(c)) == c && int64(uint8(d)) == d) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVBZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(Arg <t>))
 	// cond: is8BitInt(t) && !isSigned(t)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpArg {
@@ -8207,21 +8246,19 @@
 		if !(is8BitInt(t) && !isSigned(t)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBZreg x:(MOVBZreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -8349,20 +8386,19 @@
 	_ = b
 	// match: (MOVBreg x:(MOVBload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBreg x:(Arg <t>))
 	// cond: is8BitInt(t) && isSigned(t)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpArg {
@@ -8372,21 +8408,19 @@
 		if !(is8BitInt(t) && isSigned(t)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVBreg x:(MOVBreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -9995,7 +10029,7 @@
 	_ = b
 	// match: (MOVDload [off] {sym} ptr (MOVDstore [off2] {sym2} ptr2 x _))
 	// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		off := v.AuxInt
 		sym := v.Aux
@@ -10011,8 +10045,7 @@
 		if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -10164,6 +10197,82 @@
 	}
 	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)
+	for {
+		x := v.Args[0]
+		if !(x.Uses == 1) {
+			break
+		}
+		v.reset(OpS390XMOVDnop)
+		v.AddArg(x)
+		return true
+	}
+	return false
+}
 func rewriteValueS390X_OpS390XMOVDstore(v *Value, config *Config) bool {
 	b := v.Block
 	_ = b
@@ -10912,7 +11021,7 @@
 	_ = b
 	// match: (MOVHZload [off] {sym} ptr (MOVHstore [off2] {sym2} ptr2 x _))
 	// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		off := v.AuxInt
 		sym := v.Aux
@@ -10928,8 +11037,7 @@
 		if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -11086,33 +11194,31 @@
 	_ = b
 	// match: (MOVHZreg x:(MOVBZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHZreg x:(MOVHZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHZreg x:(Arg <t>))
 	// cond: (is8BitInt(t) || is16BitInt(t)) && !isSigned(t)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpArg {
@@ -11122,34 +11228,31 @@
 		if !((is8BitInt(t) || is16BitInt(t)) && !isSigned(t)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHZreg x:(MOVBZreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHZreg x:(MOVHZreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHZreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -11277,46 +11380,43 @@
 	_ = b
 	// match: (MOVHreg x:(MOVBload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHreg x:(MOVBZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHreg x:(MOVHload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHreg x:(Arg <t>))
 	// cond: (is8BitInt(t) || is16BitInt(t)) && isSigned(t)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpArg {
@@ -11326,47 +11426,43 @@
 		if !((is8BitInt(t) || is16BitInt(t)) && isSigned(t)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHreg x:(MOVBreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHreg x:(MOVBZreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVHreg x:(MOVHreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -12310,7 +12406,7 @@
 	_ = b
 	// match: (MOVWZload [off] {sym} ptr (MOVWstore [off2] {sym2} ptr2 x _))
 	// cond: sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		off := v.AuxInt
 		sym := v.Aux
@@ -12326,8 +12422,7 @@
 		if !(sym == sym2 && off == off2 && isSamePtr(ptr, ptr2)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -12484,46 +12579,43 @@
 	_ = b
 	// match: (MOVWZreg x:(MOVBZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWZreg x:(MOVHZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWZreg x:(MOVWZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVWZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWZreg x:(Arg <t>))
 	// cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpArg {
@@ -12533,47 +12625,43 @@
 		if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && !isSigned(t)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWZreg x:(MOVBZreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWZreg x:(MOVHZreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHZreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWZreg x:(MOVWZreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVWZreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -12701,72 +12789,67 @@
 	_ = b
 	// match: (MOVWreg x:(MOVBload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVBZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVHload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVHZload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHZload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVWload _ _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVWload {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(Arg <t>))
 	// cond: (is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpArg {
@@ -12776,73 +12859,67 @@
 		if !((is8BitInt(t) || is16BitInt(t) || is32BitInt(t)) && isSigned(t)) {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVBreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVBZreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVBZreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVHreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVHreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVHreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
 	// match: (MOVWreg x:(MOVWreg _))
 	// cond:
-	// result: x
+	// result: (MOVDreg x)
 	for {
 		x := v.Args[0]
 		if x.Op != OpS390XMOVWreg {
 			break
 		}
-		v.reset(OpCopy)
-		v.Type = x.Type
+		v.reset(OpS390XMOVDreg)
 		v.AddArg(x)
 		return true
 	}
@@ -18165,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
@@ -18175,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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/schedule.go golang-1.8-1.8.1/src/cmd/compile/internal/ssa/schedule.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/ssa/schedule.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/ssa/schedule.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/compile/internal/syntax/parser.go golang-1.8-1.8.1/src/cmd/compile/internal/syntax/parser.go
--- golang-1.8-1.8~rc3/src/cmd/compile/internal/syntax/parser.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/compile/internal/syntax/parser.go	2017-04-07 18:54:08.000000000 +0200
@@ -1634,6 +1634,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
@@ -1680,7 +1682,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 -Nru golang-1.8-1.8~rc3/src/cmd/dist/test.go golang-1.8-1.8.1/src/cmd/dist/test.go
--- golang-1.8-1.8~rc3/src/cmd/dist/test.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/dist/test.go	2017-04-07 18:54:08.000000000 +0200
@@ -15,7 +15,6 @@
 	"os/exec"
 	"path/filepath"
 	"regexp"
-	"runtime"
 	"strconv"
 	"strings"
 	"sync"
@@ -354,7 +353,7 @@
 
 	// This test needs its stdout/stderr to be terminals, so we don't run it from cmd/go's tests.
 	// See issue 18153.
-	if runtime.GOOS == "linux" {
+	if t.goos == "linux" {
 		t.tests = append(t.tests, distTest{
 			name:    "cmd_go_test_terminal",
 			heading: "cmd/go terminal test",
@@ -568,7 +567,7 @@
 		if t.gohostos == "linux" && t.goarch == "amd64" {
 			t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", "main.go")
 		}
-		if t.gohostos == "linux" && t.goarch == "amd64" {
+		if t.goos == "linux" && t.goarch == "amd64" {
 			t.registerTest("testsanitizers", "../misc/cgo/testsanitizers", "./test.bash")
 		}
 		if t.hasBash() && t.goos != "android" && !t.iOS() && t.gohostos != "windows" {
diff -Nru golang-1.8-1.8~rc3/src/cmd/go/alldocs.go golang-1.8-1.8.1/src/cmd/go/alldocs.go
--- golang-1.8-1.8~rc3/src/cmd/go/alldocs.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/go/alldocs.go	2017-04-07 18:54:08.000000000 +0200
@@ -17,7 +17,7 @@
 // 	clean       remove object files
 // 	doc         show documentation for package or symbol
 // 	env         print Go environment information
-// 	bug         print information for bug reports
+// 	bug         start a bug report
 // 	fix         run go tool fix on packages
 // 	fmt         run gofmt on package sources
 // 	generate    generate Go files by processing source
@@ -324,15 +324,14 @@
 // each named variable on its own line.
 //
 //
-// Print information for bug reports
+// Start a bug report
 //
 // Usage:
 //
 // 	go bug
 //
-// Bug prints information that helps file effective bug reports.
-//
-// Bugs may be reported at https://golang.org/issue/new.
+// Bug opens the default browser and starts a new bug report.
+// The report includes useful system information.
 //
 //
 // Run go tool fix on packages
diff -Nru golang-1.8-1.8~rc3/src/cmd/go/get.go golang-1.8-1.8.1/src/cmd/go/get.go
--- golang-1.8-1.8~rc3/src/cmd/go/get.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/go/get.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/go/go_test.go golang-1.8-1.8.1/src/cmd/go/go_test.go
--- golang-1.8-1.8~rc3/src/cmd/go/go_test.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/go/go_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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.run("env", "GOPATH")
-
-	want := filepath.Join(os.Getenv(homeEnvName()), "go")
-	got := strings.TrimSpace(tg.getStdout())
-	if got != want {
-		t.Errorf("got %q; want %q", got, want)
-	}
-}
+	tg.tempDir("home/go")
+	tg.setenv(homeEnvName(), tg.path("home"))
 
-// Test go get missing GOPATH causes go get to warn if directory doesn't exist.
-func TestMissingGOPATHGetWarnsIfNotExists(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.run("env", "GOPATH")
+	tg.grepStdout(regexp.QuoteMeta(tg.path("home/go")), "want GOPATH=$HOME/go")
 
-	tg.run("get", "-v", "github.com/golang/example/hello")
+	tg.setenv("GOROOT", tg.path("home/go"))
+	tg.run("env", "GOPATH")
+	tg.grepStdoutNot(".", "want unset GOPATH because GOROOT=$HOME/go")
 
-	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)
-	}
+	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 no warning if directory exists.
-func TestMissingGOPATHGetDoesntWarnIfExists(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 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.tempDir("home")
+	tg.setenv(homeEnvName(), tg.path("home"))
 
-	tg.setenv(homeEnvName(), tmp)
+	// 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")
 
+	// 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)
-
-	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)
-	}
-}
+	tg.tempDir("home")
+	tg.setenv(homeEnvName(), tg.path("home"))
 
-// 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", "")
+
+	// 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")
 
-// Test that with GOPATH=$GOROOT, go get should fail.
-func TestWithGOPATHEqualsGOROOTGoGetFails(t *testing.T) {
-	testenv.MustHaveExternalNetwork(t)
+	// 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 := testgo(t)
-	defer tg.cleanup()
-	tg.parallel()
-	tg.tempDir("src")
 	tg.setenv("GOPATH", tg.path("."))
-	tg.setenv("GOROOT", tg.path("."))
-	tg.runFail("get", "-d", "golang.org/x/codereview/cmd/hgpatch")
+	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")
@@ -3744,6 +3700,13 @@
 	tg.grepBoth(okPattern, "go test did not say ok")
 }
 
+// Issue 18845
+func TestBenchTimeout(t *testing.T) {
+	tg := testgo(t)
+	defer tg.cleanup()
+	tg.run("test", "-bench", ".", "-timeout", "750ms", "testdata/timeoutbench_test.go")
+}
+
 func TestLinkXImportPathEscape(t *testing.T) {
 	// golang.org/issue/16710
 	tg := testgo(t)
diff -Nru golang-1.8-1.8~rc3/src/cmd/go/main.go golang-1.8-1.8.1/src/cmd/go/main.go
--- golang-1.8-1.8~rc3/src/cmd/go/main.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/go/main.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/go/pkg.go golang-1.8-1.8.1/src/cmd/go/pkg.go
--- golang-1.8-1.8~rc3/src/cmd/go/pkg.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/go/pkg.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/go/testdata/timeoutbench_test.go golang-1.8-1.8.1/src/cmd/go/testdata/timeoutbench_test.go
--- golang-1.8-1.8~rc3/src/cmd/go/testdata/timeoutbench_test.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/go/testdata/timeoutbench_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -0,0 +1,10 @@
+package timeoutbench_test
+
+import (
+	"testing"
+	"time"
+)
+
+func BenchmarkSleep1s(b *testing.B) {
+	time.Sleep(1 * time.Second)
+}
diff -Nru golang-1.8-1.8~rc3/src/cmd/go/test.go golang-1.8-1.8.1/src/cmd/go/test.go
--- golang-1.8-1.8~rc3/src/cmd/go/test.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/go/test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/link/dwarf_test.go golang-1.8-1.8.1/src/cmd/link/dwarf_test.go
--- golang-1.8-1.8~rc3/src/cmd/link/dwarf_test.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/link/dwarf_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/link/internal/ld/config.go golang-1.8-1.8.1/src/cmd/link/internal/ld/config.go
--- golang-1.8-1.8~rc3/src/cmd/link/internal/ld/config.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/link/internal/ld/config.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/link/internal/ld/lib.go golang-1.8-1.8.1/src/cmd/link/internal/ld/lib.go
--- golang-1.8-1.8~rc3/src/cmd/link/internal/ld/lib.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/link/internal/ld/lib.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/link/internal/ld/macho_combine_dwarf.go golang-1.8-1.8.1/src/cmd/link/internal/ld/macho_combine_dwarf.go
--- golang-1.8-1.8~rc3/src/cmd/link/internal/ld/macho_combine_dwarf.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/link/internal/ld/macho_combine_dwarf.go	2017-04-07 18:54:08.000000000 +0200
@@ -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()
+
+	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
+	}
 
-	delta := uint64(dwarfstart) - realdwarf.Offset
-	offset.SetUint(offset.Uint() + delta)
 	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 -Nru golang-1.8-1.8~rc3/src/cmd/link/internal/ld/macho.go golang-1.8-1.8.1/src/cmd/link/internal/ld/macho.go
--- golang-1.8-1.8~rc3/src/cmd/link/internal/ld/macho.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/link/internal/ld/macho.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/link/internal/ppc64/asm.go golang-1.8-1.8.1/src/cmd/link/internal/ppc64/asm.go
--- golang-1.8-1.8~rc3/src/cmd/link/internal/ppc64/asm.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/link/internal/ppc64/asm.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/cmd/link/linkbig_test.go golang-1.8-1.8.1/src/cmd/link/linkbig_test.go
--- golang-1.8-1.8~rc3/src/cmd/link/linkbig_test.go	2017-01-26 19:54:57.000000000 +0100
+++ golang-1.8-1.8.1/src/cmd/link/linkbig_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/crypto/tls/common.go golang-1.8-1.8.1/src/crypto/tls/common.go
--- golang-1.8-1.8~rc3/src/crypto/tls/common.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/crypto/tls/common.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/crypto/tls/tls_test.go golang-1.8-1.8.1/src/crypto/tls/tls_test.go
--- golang-1.8-1.8~rc3/src/crypto/tls/tls_test.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/crypto/tls/tls_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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
-
-		}
-
-		q, ok := quick.Value(f.Type(), rnd)
-		if !ok {
-			t.Fatalf("quick.Value failed on field %s", fn)
+		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)
 		}
-		f.Set(q)
 	}
 
 	c2 := c1.Clone()
diff -Nru golang-1.8-1.8~rc3/src/crypto/x509/root_linux.go golang-1.8-1.8.1/src/crypto/x509/root_linux.go
--- golang-1.8-1.8~rc3/src/crypto/x509/root_linux.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/crypto/x509/root_linux.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/database/sql/ctxutil.go golang-1.8-1.8.1/src/database/sql/ctxutil.go
--- golang-1.8-1.8~rc3/src/database/sql/ctxutil.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/database/sql/ctxutil.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/database/sql/sql.go golang-1.8-1.8.1/src/database/sql/sql.go
--- golang-1.8-1.8~rc3/src/database/sql/sql.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/database/sql/sql.go	2017-04-07 18:54:08.000000000 +0200
@@ -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
+
+	if rs.lasterr == nil {
+		rs.lasterr = err
+	}
 
-	err := rs.rowsi.Close()
+	err = rs.rowsi.Close()
 	if fn := rowsCloseHook(); fn != nil {
 		fn(rs, &err)
 	}
diff -Nru golang-1.8-1.8~rc3/src/database/sql/sql_test.go golang-1.8-1.8.1/src/database/sql/sql_test.go
--- golang-1.8-1.8~rc3/src/database/sql/sql_test.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/database/sql/sql_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/encoding/xml/marshal.go golang-1.8-1.8.1/src/encoding/xml/marshal.go
--- golang-1.8-1.8~rc3/src/encoding/xml/marshal.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/encoding/xml/marshal.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/encoding/xml/marshal_test.go golang-1.8-1.8.1/src/encoding/xml/marshal_test.go
--- golang-1.8-1.8~rc3/src/encoding/xml/marshal_test.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/encoding/xml/marshal_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/encoding/xml/read.go golang-1.8-1.8.1/src/encoding/xml/read.go
--- golang-1.8-1.8~rc3/src/encoding/xml/read.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/encoding/xml/read.go	2017-04-07 18:54:08.000000000 +0200
@@ -285,7 +285,8 @@
 		return nil
 	}
 
-	return copyValue(val, []byte(attr.Value))
+	copyValue(val, []byte(attr.Value))
+	return nil
 }
 
 var (
diff -Nru golang-1.8-1.8~rc3/src/encoding/xml/xml_test.go golang-1.8-1.8.1/src/encoding/xml/xml_test.go
--- golang-1.8-1.8~rc3/src/encoding/xml/xml_test.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/encoding/xml/xml_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/go/build/build.go golang-1.8-1.8.1/src/go/build/build.go
--- golang-1.8-1.8~rc3/src/go/build/build.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/go/build/build.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/image/png/reader.go golang-1.8-1.8.1/src/image/png/reader.go
--- golang-1.8-1.8~rc3/src/image/png/reader.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/image/png/reader.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/image/png/reader_test.go golang-1.8-1.8.1/src/image/png/reader_test.go
--- golang-1.8-1.8~rc3/src/image/png/reader_test.go	2017-01-26 19:54:58.000000000 +0100
+++ golang-1.8-1.8.1/src/image/png/reader_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/internal/testenv/testenv_cgo.go golang-1.8-1.8.1/src/internal/testenv/testenv_cgo.go
--- golang-1.8-1.8~rc3/src/internal/testenv/testenv_cgo.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/src/internal/testenv/testenv_cgo.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/internal/testenv/testenv.go golang-1.8-1.8.1/src/internal/testenv/testenv.go
--- golang-1.8-1.8~rc3/src/internal/testenv/testenv.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/internal/testenv/testenv.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/net/http/http.go golang-1.8-1.8.1/src/net/http/http.go
--- golang-1.8-1.8~rc3/src/net/http/http.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/net/http/http.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/net/net.go golang-1.8-1.8.1/src/net/net.go
--- golang-1.8-1.8~rc3/src/net/net.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/net/net.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/os/exec/exec_test.go golang-1.8-1.8.1/src/os/exec/exec_test.go
--- golang-1.8-1.8~rc3/src/os/exec/exec_test.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/os/exec/exec_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/reflect/all_test.go golang-1.8-1.8.1/src/reflect/all_test.go
--- golang-1.8-1.8~rc3/src/reflect/all_test.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/reflect/all_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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))
 	}
 }
 
diff -Nru golang-1.8-1.8~rc3/src/reflect/type.go golang-1.8-1.8.1/src/reflect/type.go
--- golang-1.8-1.8~rc3/src/reflect/type.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/reflect/type.go	2017-04-07 18:54:08.000000000 +0200
@@ -1469,6 +1469,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 -Nru golang-1.8-1.8~rc3/src/reflect/value.go golang-1.8-1.8.1/src/reflect/value.go
--- golang-1.8-1.8~rc3/src/reflect/value.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/reflect/value.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/runtime/crash_unix_test.go golang-1.8-1.8.1/src/runtime/crash_unix_test.go
--- golang-1.8-1.8~rc3/src/runtime/crash_unix_test.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/runtime/crash_unix_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/runtime/export_test.go golang-1.8-1.8.1/src/runtime/export_test.go
--- golang-1.8-1.8~rc3/src/runtime/export_test.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/runtime/export_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/runtime/mgc.go golang-1.8-1.8.1/src/runtime/mgc.go
--- golang-1.8-1.8~rc3/src/runtime/mgc.go	2017-01-26 19:54:59.000000000 +0100
+++ golang-1.8-1.8.1/src/runtime/mgc.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/runtime/runtime1.go golang-1.8-1.8.1/src/runtime/runtime1.go
--- golang-1.8-1.8~rc3/src/runtime/runtime1.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/runtime/runtime1.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/runtime/sema.go golang-1.8-1.8.1/src/runtime/sema.go
--- golang-1.8-1.8~rc3/src/runtime/sema.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/runtime/sema.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/runtime/signal_sighandler.go golang-1.8-1.8.1/src/runtime/signal_sighandler.go
--- golang-1.8-1.8~rc3/src/runtime/signal_sighandler.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/runtime/signal_sighandler.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/runtime/testdata/testprogcgo/threadpprof.go golang-1.8-1.8.1/src/runtime/testdata/testprogcgo/threadpprof.go
--- golang-1.8-1.8~rc3/src/runtime/testdata/testprogcgo/threadpprof.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/runtime/testdata/testprogcgo/threadpprof.go	2017-04-07 18:54:08.000000000 +0200
@@ -61,7 +61,7 @@
 	return 0;
 }
 
-void runCPUHogThread() {
+void runCPUHogThread(void) {
 	pthread_t tid;
 	pthread_create(&tid, 0, cpuHogDriver, 0);
 }
diff -Nru golang-1.8-1.8~rc3/src/runtime/testdata/testprogcgo/traceback.go golang-1.8-1.8.1/src/runtime/testdata/testprogcgo/traceback.go
--- golang-1.8-1.8~rc3/src/runtime/testdata/testprogcgo/traceback.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/runtime/testdata/testprogcgo/traceback.go	2017-04-07 18:54:08.000000000 +0200
@@ -15,16 +15,16 @@
 
 char *p;
 
-static int f3() {
+static int f3(void) {
 	*p = 0;
 	return 0;
 }
 
-static int f2() {
+static int f2(void) {
 	return f3();
 }
 
-static int f1() {
+static int f1(void) {
 	return f2();
 }
 
diff -Nru golang-1.8-1.8~rc3/src/testing/testing.go golang-1.8-1.8.1/src/testing/testing.go
--- golang-1.8-1.8~rc3/src/testing/testing.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/testing/testing.go	2017-04-07 18:54:08.000000000 +0200
@@ -821,6 +821,7 @@
 	haveExamples = len(m.examples) > 0
 	testRan, testOk := runTests(m.deps.MatchString, m.tests)
 	exampleRan, exampleOk := runExamples(m.deps.MatchString, m.examples)
+	stopAlarm()
 	if !testRan && !exampleRan && *matchBenchmarks == "" {
 		fmt.Fprintln(os.Stderr, "testing: warning: no tests to run")
 	}
diff -Nru golang-1.8-1.8~rc3/src/text/template/multi_test.go golang-1.8-1.8.1/src/text/template/multi_test.go
--- golang-1.8-1.8~rc3/src/text/template/multi_test.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/text/template/multi_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/text/template/template.go golang-1.8-1.8.1/src/text/template/template.go
--- golang-1.8-1.8~rc3/src/text/template/template.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/text/template/template.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/time/format_test.go golang-1.8-1.8.1/src/time/format_test.go
--- golang-1.8-1.8~rc3/src/time/format_test.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/time/format_test.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/const_amd64.h golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/const_amd64.h
--- golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/const_amd64.h	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/const_amd64.h	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/const_amd64.s golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/const_amd64.s
--- golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/const_amd64.s	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/const_amd64.s	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/freeze_amd64.s golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/freeze_amd64.s
--- golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/freeze_amd64.s	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/freeze_amd64.s	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/ladderstep_amd64.s golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/ladderstep_amd64.s
--- golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/ladderstep_amd64.s	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/ladderstep_amd64.s	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/mul_amd64.s golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/mul_amd64.s
--- golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/mul_amd64.s	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/mul_amd64.s	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/square_amd64.s golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/square_amd64.s
--- golang-1.8-1.8~rc3/src/vendor/golang_org/x/crypto/curve25519/square_amd64.s	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/src/vendor/golang_org/x/crypto/curve25519/square_amd64.s	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/bug19403.go golang-1.8-1.8.1/test/fixedbugs/bug19403.go
--- golang-1.8-1.8~rc3/test/fixedbugs/bug19403.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/bug19403.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue18808.go golang-1.8-1.8.1/test/fixedbugs/issue18808.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue18808.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue18808.go	2017-04-07 18:54:08.000000000 +0200
@@ -0,0 +1,63 @@
+// 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
+
+const lim = 0x80000000
+
+//go:noinline
+func eq(x uint32) {
+	if x == lim {
+		return
+	}
+	panic("x == lim returned false")
+}
+
+//go:noinline
+func neq(x uint32) {
+	if x != lim {
+		panic("x != lim returned true")
+	}
+}
+
+//go:noinline
+func gt(x uint32) {
+	if x > lim {
+		return
+	}
+	panic("x > lim returned false")
+}
+
+//go:noinline
+func gte(x uint32) {
+	if x >= lim {
+		return
+	}
+	panic("x >= lim returned false")
+}
+
+//go:noinline
+func lt(x uint32) {
+	if x < lim {
+		panic("x < lim returned true")
+	}
+}
+
+//go:noinline
+func lte(x uint32) {
+	if x <= lim {
+		panic("x <= lim returned true")
+	}
+}
+
+func main() {
+	eq(lim)
+	neq(lim)
+	gt(lim+1)
+	gte(lim+1)
+	lt(lim+1)
+	lte(lim+1)
+}
diff -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue18906.go golang-1.8-1.8.1/test/fixedbugs/issue18906.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue18906.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue18906.go	2017-04-07 18:54:08.000000000 +0200
@@ -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
+
+//go:noinline
+func f(x int) {
+}
+
+//go:noinline
+func val() int8 {
+	return -1
+}
+
+var (
+	array = [257]int{}
+	slice = array[1:]
+)
+
+func init() {
+	for i := range array {
+		array[i] = i - 1
+	}
+}
+
+func main() {
+	x := val()
+	y := int(uint8(x))
+	f(y) // try and force y to be calculated and spilled
+	if slice[y] != 255 {
+		panic("incorrect value")
+	}
+}
diff -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue18915.go golang-1.8-1.8.1/test/fixedbugs/issue18915.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue18915.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue18915.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue19137.go golang-1.8-1.8.1/test/fixedbugs/issue19137.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue19137.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue19137.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue19168.go golang-1.8-1.8.1/test/fixedbugs/issue19168.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue19168.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue19168.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue19182.go golang-1.8-1.8.1/test/fixedbugs/issue19182.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue19182.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue19182.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue19201.go golang-1.8-1.8.1/test/fixedbugs/issue19201.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue19201.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue19201.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue19217.go golang-1.8-1.8.1/test/fixedbugs/issue19217.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue19217.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue19217.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue19323.go golang-1.8-1.8.1/test/fixedbugs/issue19323.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue19323.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue19323.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue19743.go golang-1.8-1.8.1/test/fixedbugs/issue19743.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue19743.go	1970-01-01 01:00:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue19743.go	2017-04-07 18:54:08.000000000 +0200
@@ -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 -Nru golang-1.8-1.8~rc3/test/fixedbugs/issue6036.go golang-1.8-1.8.1/test/fixedbugs/issue6036.go
--- golang-1.8-1.8~rc3/test/fixedbugs/issue6036.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/test/fixedbugs/issue6036.go	2017-04-07 18:54:08.000000000 +0200
@@ -1,4 +1,4 @@
-// +build amd64
+// +build !386,!arm,!mips,!mipsle,!amd64p32
 // compile
 
 // Copyright 2013 The Go Authors. All rights reserved.
diff -Nru golang-1.8-1.8~rc3/test/writebarrier.go golang-1.8-1.8.1/test/writebarrier.go
--- golang-1.8-1.8~rc3/test/writebarrier.go	2017-01-26 19:55:00.000000000 +0100
+++ golang-1.8-1.8.1/test/writebarrier.go	2017-04-07 18:54:08.000000000 +0200
@@ -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"
+}
diff -Nru golang-1.8-1.8~rc3/VERSION golang-1.8-1.8.1/VERSION
--- golang-1.8-1.8~rc3/VERSION	2017-01-26 19:55:01.000000000 +0100
+++ golang-1.8-1.8.1/VERSION	2017-04-07 18:54:11.000000000 +0200
@@ -1 +1 @@
-go1.8rc3
\ No newline at end of file
+go1.8.1
\ No newline at end of file

Reply to: