Compare commits

..

13 Commits

Author SHA1 Message Date
Rick Hudson
1d4942afe0 [dev.garbage] runtime: determine if an object is public
ROC (request oriented collector) needs to determine
if an object is visible to other goroutines, i.e.
public. In a later CL this will be used by the write
barrier and the publishing logic to distinguish between
local and public objects and act accordingly.

Change-Id: I6a80da9deb21f57e831a2ec04e41477f997a8c33
Reviewed-on: https://go-review.googlesource.com/25056
Reviewed-by: Austin Clements <austin@google.com>
2017-05-25 18:05:53 +00:00
Austin Clements
8b25a00e6d Merge branch 'master' into dev.garbage
Change-Id: I36274cf72b8e1908efc8e375cab7880d7b0b3f43
2017-01-11 11:34:07 -05:00
Austin Clements
42afbd9e63 Merge branch 'master' into dev.garbage
Sync to 1.8 beta 1.

Change-Id: Iddd3773babd8fe50aed791ef7150d0c7c455cc8d
2016-12-05 12:15:50 -05:00
Austin Clements
f9f6c90ed1 [dev.garbage] Merge branch 'master' into dev.garbage
This merges master as of the Go 1.7 release.

Change-Id: I95ac0f96a0837173a2b8d7e8aaadf6fecc1baeaf
2016-08-25 11:55:08 -04:00
Rick Hudson
69161e279e [dev.garbage] runtime: Add GODEBUG=gcroc=n
Add command line boilerplace that turns the ROC algorithm on.
gcroc=0 or not specified:
	does not turn ROC on but some benign code may run.
gcroc=1
	simply turns the algorithm on
gcroc>1
	same as gcroc but with increasing levels of diagnostics
	being turned on. Expect gcroc>1 to not be as performant as
	gcroc=1

Change-Id: I6348b6768f7a3f8c2f69ef01ea20efebf992029e
Reviewed-on: https://go-review.googlesource.com/21368
Reviewed-by: Austin Clements <austin@google.com>
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2016-07-26 13:21:53 +00:00
Austin Clements
fb4c718209 [dev.garbage] Merge branch 'master' into dev.garbage
Change-Id: I8ba4b012d82921f9521f471b1c0b5a1f6149a986
2016-07-19 17:54:41 -04:00
Austin Clements
81b74bf9c5 [dev.garbage] runtime: make _TinySizeClass an int8 to prevent use as spanClass
Currently _TinySizeClass is untyped, which means it can accidentally
be used as a spanClass (not that I would know this from experience or
anything). Make it an int8 to avoid this mix up.

Change-Id: I1e69eccee436ea5aa45e9a9828a013e369e03f1a
Reviewed-on: https://go-review.googlesource.com/24372
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rick Hudson <rlh@golang.org>
2016-06-23 16:26:08 +00:00
Austin Clements
edb54c300f [dev.garbage] runtime: eliminate heapBitsSetTypeNoScan
It's no longer necessary to maintain the bitmap of noscan objects
since we now use the span metadata to determine that they're noscan
instead of the bitmap.

The combined effect of segregating noscan spans and the follow-on
optimizations is almost no effect on the go1 benchmarks and a 1.19%
improvement in the garbage benchmark:

name              old time/op  new time/op  delta
XBenchGarbage-12  2.13ms ± 2%  2.11ms ± 1%  -1.19%  (p=0.000 n=19+20)

name                      old time/op    new time/op    delta
BinaryTree17-12              2.42s ± 1%     2.41s ± 1%  -0.50%  (p=0.001 n=20+17)
Fannkuch11-12                2.14s ± 0%     2.12s ± 0%  -0.91%  (p=0.000 n=20+17)
FmtFprintfEmpty-12          45.2ns ± 0%    45.2ns ± 1%    ~     (p=0.677 n=16+19)
FmtFprintfString-12          131ns ± 0%     132ns ± 1%  +0.57%  (p=0.000 n=16+20)
FmtFprintfInt-12             126ns ± 1%     126ns ± 0%    ~     (p=0.078 n=18+16)
FmtFprintfIntInt-12          199ns ± 0%     195ns ± 0%  -2.19%  (p=0.000 n=14+20)
FmtFprintfPrefixedInt-12     196ns ± 1%     196ns ± 0%    ~     (p=0.155 n=19+16)
FmtFprintfFloat-12           254ns ± 0%     253ns ± 0%  -0.50%  (p=0.000 n=14+19)
FmtManyArgs-12               803ns ± 1%     798ns ± 0%  -0.71%  (p=0.000 n=18+19)
GobDecode-12                7.11ms ± 1%    7.07ms ± 1%  -0.50%  (p=0.024 n=18+19)
GobEncode-12                5.87ms ± 0%    5.86ms ± 1%    ~     (p=0.113 n=19+20)
Gzip-12                      218ms ± 1%     218ms ± 1%    ~     (p=0.879 n=19+20)
Gunzip-12                   37.2ms ± 0%    37.3ms ± 0%  +0.14%  (p=0.047 n=19+20)
HTTPClientServer-12         80.5µs ± 6%    82.8µs ± 8%  +2.91%  (p=0.008 n=19+20)
JSONEncode-12               15.4ms ± 1%    15.4ms ± 1%  -0.32%  (p=0.003 n=18+19)
JSONDecode-12               55.1ms ± 1%    53.0ms ± 1%  -3.87%  (p=0.000 n=18+20)
Mandelbrot200-12            4.08ms ± 1%    4.10ms ± 1%  +0.34%  (p=0.001 n=19+17)
GoParse-12                  3.20ms ± 1%    3.21ms ± 1%    ~     (p=0.138 n=19+19)
RegexpMatchEasy0_32-12      70.6ns ± 2%    70.4ns ± 2%    ~     (p=0.343 n=20+20)
RegexpMatchEasy0_1K-12       240ns ± 0%     242ns ± 2%  +0.88%  (p=0.000 n=15+20)
RegexpMatchEasy1_32-12      70.5ns ± 1%    70.2ns ± 3%    ~     (p=0.053 n=18+20)
RegexpMatchEasy1_1K-12       374ns ± 1%     374ns ± 1%    ~     (p=0.705 n=20+19)
RegexpMatchMedium_32-12      108ns ± 1%     108ns ± 1%    ~     (p=0.854 n=20+19)
RegexpMatchMedium_1K-12     33.5µs ± 1%    33.6µs ± 2%    ~     (p=0.897 n=18+20)
RegexpMatchHard_32-12       1.76µs ± 1%    1.75µs ± 1%    ~     (p=0.771 n=18+18)
RegexpMatchHard_1K-12       52.8µs ± 1%    52.8µs ± 1%    ~     (p=0.678 n=17+19)
Revcomp-12                   381ms ± 1%     380ms ± 0%    ~     (p=0.320 n=20+16)
Template-12                 65.6ms ± 1%    65.1ms ± 2%  -0.75%  (p=0.003 n=20+20)
TimeParse-12                 324ns ± 1%     326ns ± 1%  +0.72%  (p=0.000 n=18+18)
TimeFormat-12                342ns ± 0%     343ns ± 1%  +0.22%  (p=0.004 n=15+18)
[Geo mean]                  52.4µs         52.3µs       -0.18%

Change-Id: Ic77faaa15cdac3bfbbb0032dde5c204e05a0fd8e
Reviewed-on: https://go-review.googlesource.com/23702
Reviewed-by: Rick Hudson <rlh@golang.org>
2016-06-15 21:17:15 +00:00
Austin Clements
312aa09996 [dev.garbage] runtime: eliminate heapBits.hasPointers
This is no longer necessary now that we can more efficiently consult
the span's noscan bit.

Change-Id: Id0b00b278533660973f45eb6efa5b00f373d58af
Reviewed-on: https://go-review.googlesource.com/23701
Reviewed-by: Rick Hudson <rlh@golang.org>
2016-06-15 21:17:04 +00:00
Austin Clements
d491e550c3 [dev.garbage] runtime: separate spans of noscan objects
Currently, we mix objects with pointers and objects without pointers
("noscan" objects) together in memory. As a result, for every object
we grey, we have to check that object's heap bits to find out if it's
noscan, which adds to the per-object cost of GC. This also hurts the
TLB footprint of the garbage collector because it decreases the
density of scannable objects at the page level.

This commit improves the situation by using separate spans for noscan
objects. This will allow a much simpler noscan check (in a follow up
CL), eliminate the need to clear the bitmap of noscan objects (in a
follow up CL), and improves TLB footprint by increasing the density of
scannable objects.

This is also a step toward eliminating dead bits, since the current
noscan check depends on checking the dead bit of the first word.

This has no effect on the heap size of the garbage benchmark.

We'll measure the performance change of this after the follow-up
optimizations.

Change-Id: I13bdc4869538ece5649a8d2a41c6605371618e40
Reviewed-on: https://go-review.googlesource.com/23700
Reviewed-by: Rick Hudson <rlh@golang.org>
2016-06-15 21:16:53 +00:00
Austin Clements
641c32dafa [dev.garbage] Merge branch 'master' into dev.garbage
Change-Id: I7ab2afca656e8c145804d9823cd084b8a85bccd7
2016-06-06 10:01:41 -04:00
Austin Clements
2e495a1df6 [dev.garbage] Merge branch 'master' into dev.garbage
Change-Id: I35edefb4464566601850081ecc84dd3535d60ceb
2016-05-16 14:29:53 -04:00
Austin Clements
344476d23c [dev.garbage] Merge branch 'master' into dev.garbage
Change-Id: I2e04fd9e7071efe33ce76f2f10a8dbde53ba90b9
2016-05-09 14:49:54 -04:00
234 changed files with 1693 additions and 8005 deletions

View File

@@ -5,37 +5,39 @@ reliable, and efficient software.
![Gopher image](doc/gopher/fiveyears.jpg)
For documentation about how to install and use Go,
visit https://golang.org/ or load doc/install-source.html
in your web browser.
Our canonical Git repository is located at https://go.googlesource.com/go.
There is a mirror of the repository at https://github.com/golang/go.
Unless otherwise noted, the Go source files are distributed under the
BSD-style license found in the LICENSE file.
### Download and Install
#### Binary Distributions
Official binary distributions are available at https://golang.org/dl/.
After downloading a binary release, visit https://golang.org/doc/install
or load doc/install.html in your web browser for installation
instructions.
#### Install From Source
If a binary distribution is not available for your combination of
operating system and architecture, visit
https://golang.org/doc/install/source or load doc/install-source.html
in your web browser for source installation instructions.
### Contributing
Go is the work of hundreds of contributors. We appreciate your help!
To contribute, please read the contribution guidelines:
https://golang.org/doc/contribute.html
Note that the Go project does not use GitHub pull requests, and that
we use the issue tracker for bug reports and proposals only. See
https://golang.org/wiki/Questions for a list of places to ask
questions about the Go language.
##### Note that we do not accept pull requests and that we use the issue tracker for bug reports and proposals only. Please ask questions on https://forum.golangbridge.org or https://groups.google.com/forum/#!forum/golang-nuts.
Unless otherwise noted, the Go source files are distributed
under the BSD-style license found in the LICENSE file.
--
## Binary Distribution Notes
If you have just untarred a binary Go distribution, you need to set
the environment variable $GOROOT to the full path of the go
directory (the one containing this file). You can omit the
variable if you unpack it into /usr/local/go, or if you rebuild
from sources by running all.bash (see doc/install-source.html).
You should also add the Go binary directory $GOROOT/bin
to your shell's path.
For example, if you extracted the tar file into $HOME/go, you might
put the following in your .profile:
export GOROOT=$HOME/go
export PATH=$PATH:$GOROOT/bin
See https://golang.org/doc/install or doc/install.html for more details.

View File

@@ -1 +0,0 @@
go1.8.4

View File

@@ -22,6 +22,8 @@ using the go <code>tool</code> subcommand, such as <code>go tool vet</code>.
This style of invocation allows, for instance, checking a single source file
rather than an entire package: <code>go tool vet myprogram.go</code> as
compared to <code>go vet mypackage</code>.
Some of the commands, such as <code>yacc</code>, are accessible only through
the go <code>tool</code> subcommand.
</p>
<p>
@@ -93,6 +95,12 @@ gofmt</a> command with more general options.</td>
calls whose arguments do not align with the format string.</td>
</tr>
<tr>
<td><a href="/cmd/yacc/">yacc</a></td>
<td>&nbsp;&nbsp;&nbsp;&nbsp;</td>
<td>Yacc is a version of yacc that generates parsers implemented in Go.</td>
</tr>
</table>
<p>

View File

@@ -148,26 +148,29 @@ These actions are explicitly forbidden in Go spaces:
<p>
The Go spaces are not free speech venues; they are for discussion about Go.
Each of these spaces have their own moderators.
These spaces have moderators.
The goal of the moderators is to facilitate civil discussion about Go.
</p>
<p>
When using the official Go spaces you should act in the spirit of the “Gopher
values”.
If a reported conflict cannot be resolved amicably, the CoC Working Group
may make a recommendation to the relevant forum moderators.
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.
</p>
<p>
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.
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.
</p>
<p>
Complaints about working group member or moderator actions must be handled
using the reporting process below.
Complaints about moderator actions must be handled using the reporting process
below.
</p>
<h2 id="reporting">Reporting issues</h2>
@@ -182,6 +185,8 @@ satisfaction of all parties. They are:
<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;
@@ -196,10 +201,13 @@ particular individual or group.
</p>
<ul>
<li>Mail <a href="mailto:conduct@golang.org">conduct@golang.org</a>.
<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>.
<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
@@ -221,8 +229,11 @@ particular individual or group.
<li>The Working Group will reach a decision as to how to act. These may include:
<ul>
<li>Nothing.
<li>Passing the report along to the offender.
<li>A recommendation of action to the relevant forum moderators.
<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.
</ul>
<li>The Working Group will reach out to the original reporter to let them know
the decision.
@@ -235,6 +246,7 @@ particular individual or group.
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>

View File

@@ -34,7 +34,6 @@ We encourage all Go users to subscribe to
<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>

View File

@@ -1,12 +1,14 @@
<!--{
"Title": "Contribution Guide"
"Title": "Contribution Guidelines"
}-->
<h2 id="Introduction">Introduction</h2>
<p>
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.
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>.
</p>
<p>
@@ -18,54 +20,103 @@ see <a href="gccgo_contribute.html">Contributing to gccgo</a>.)
Sensitive security-related issues should be reported to <a href="mailto:security@golang.org">security@golang.org</a>.
</p>
<h1 id="contributor">Becoming a contributor</h1>
<h2 id="Design">Discuss your design</h2>
<p>
Before you can contribute to the Go project you need to setup a few prerequisites.
The Go project uses <a href="https://www.gerritcodereview.com/">Gerrit</a>, an open
source online tool, to perform all code reviews.
Gerrit uses your email address as a unique identifier.
The Go project contributing flow is currently configured to work only with Google Accounts.
You must go through the following process <em>prior to contributing</em>.
You only need to do this once per Google Account.
</p>
<h2 id="auth">Configure Git to use Gerrit</h2>
<p>
You'll need a web browser and a command line terminal.
You should already have Git installed.
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>
Gerrit uses Google Accounts for authentication.
If you don't have a Google Account, you can create an account which
Before undertaking to write something new for the Go project,
please <a href="https://golang.org/issue/new">file an issue</a>
(or claim an <a href="https://golang.org/issues">existing issue</a>).
Significant changes must go through the
<a href="https://golang.org/s/proposal-process">change proposal process</a>
before they can be accepted.
</p>
<p>
This process gives everyone a chance to validate the design,
helps prevent duplication of effort,
and ensures that the idea fits inside the goals for the language and tools.
It also checks that the design is sound before code is written;
the code review tool is not the place for high-level discussions.
</p>
<p>
When planning work, please note that the Go project follows a
<a href="https://golang.org/wiki/Go-Release-Cycle">six-month
development cycle</a>. The latter half of each cycle is a three-month
feature freeze during which only bug fixes and doc updates are accepted.
New work cannot be submitted during a feature freeze.
</p>
<h2 id="Testing">Testing redux</h2>
<p>
You've <a href="code.html">written and tested your code</a>, but
before sending code out for review, run all the tests for the whole
tree to make sure the changes don't break other packages or programs:
</p>
<pre>
$ cd go/src
$ ./all.bash
</pre>
<p>
(To build under Windows use <code>all.bat</code>.)
</p>
<p>
After running for a while, the command should print
"<code>ALL</code> <code>TESTS</code> <code>PASSED</code>".
</p>
<h2 id="Code_review">Code review</h2>
<p>
Changes to Go must be reviewed before they are accepted,
no matter who makes the change.
A custom git command called <code>git-codereview</code>,
discussed below, helps manage the code review process through a Google-hosted
<a href="https://go-review.googlesource.com/">instance</a> of the code review
system called <a href="https://www.gerritcodereview.com/">Gerrit</a>.
</p>
<h3 id="auth">Set up authentication for code review</h3>
<p>
Gerrit uses Google Accounts for authentication. If you don't have
a Google Account, you can create an account which
<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>
<h3>Step 1: Sign in to googlesource and generate a password</h3>
<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>
<p>
Visit <a href="https://go.googlesource.com">go.googlesource.com</a>
To set up your account in Gerrit, visit
<a href="https://go.googlesource.com">go.googlesource.com</a>
and click on "Generate Password" in the page's top right menu bar.
</p>
<p>
You will be redirected to accounts.google.com to sign in.
</p>
<h3>Step 2: Run the provided script</h3>
<p>
After signing in, you are taken to a page on go.googlesource.com with the title "Configure Git".
This page contains a personalized script which when run locally will configure git
to have your unique authentication key.
This key is paired with one generated server side similar to how ssh keys work.
</p>
<p>
Copy and run this script locally in your command line terminal.
(On a Windows computer using cmd you should instead follow the instructions
in the yellow box to run the command. If you are using git-bash use the same
script as *nix.)
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.)
</p>
<p>
@@ -73,25 +124,23 @@ Your secret authentication token is now in a <code>.gitcookie</code> file
and Git is configured to use this file.
</p>
<h3 id="gerrit">Step 3: Register with Gerrit</h3>
<h3 id="gerrit">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>.
Sign in using the same Google Account you used above.
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.
</p>
<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>
<h3 id="cla">Contributor License Agreement</h3>
<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
@@ -102,49 +151,37 @@ contributor license agreement</a>, which can be completed online.
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>.<br>
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.)
</li>
</ul>
<p>
<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>,
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>,
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>
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.
This rigmarole only needs to be done for your first submission for each email address.
</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>
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.
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.
</p>
<h3 id="git-codereview_install">Install the git-codereview command</h3>
<h3 id="git-codereview">Install the git-codereview command</h3>
<p>
Install the <code>git-codereview</code> command by running,
Now install the <code>git-codereview</code> command by running,
</p>
<pre>
@@ -164,29 +201,19 @@ $ git codereview help
prints help text, not an error.
</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>
@@ -237,8 +264,7 @@ To install them, copy this text into your Git configuration file
sync = codereview sync
</pre>
<span id="help"></span>
<h3 id="understanding_git-codereview">Understanding the git-codereview command</h3>
<h3 id="help">Understanding the git-codereview command</h3>
<p>After installing the <code>git-codereview</code> command, you can run</p>
@@ -251,70 +277,11 @@ to learn more about its commands.
You can also read the <a href="https://godoc.org/golang.org/x/review/git-codereview">command documentation</a>.
</p>
<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>
<h3 id="master">Switch to the master branch</h3>
<p>
Most Go installations use a release branch, but new changes should
only be made based on the master branch. <br>
only be made based on the master branch.
(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:
@@ -330,61 +297,10 @@ $ git sync
<code>git</code> <code>pull</code> <code>-r</code>.)
</p>
<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>
<h3 id="change">Make a change</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,
@@ -395,19 +311,16 @@ and
</p>
<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>
If you wish to checkpoint your work, or are ready to send the code out for review, run</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 and will not be used elsewhere.
This is an offline operation and nothing will be sent to the server yet.
local branch containing your changes.
</p>
<p>
@@ -418,11 +331,9 @@ then <code>git</code> <code>commit</code>.)
</p>
<p>
As the `git commit` is the final step, Git will open an editor to ask for a
commit message.
Git will open a change description file in your editor.
(It uses the editor named by the <code>$EDITOR</code> environment variable,
<code>vi</code> by default.)
The file will look like:
</p>
@@ -441,7 +352,7 @@ At the beginning of this file is a blank line; replace it
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 email.
and is used as the subject for code review mail.
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.
@@ -484,7 +395,7 @@ the command and move that file to a different branch.
<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 applied, the issue
When this change is eventually submitted, 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>.)
@@ -495,13 +406,6 @@ Once you have finished writing the commit message,
save the file and exit the editor.
</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
@@ -512,8 +416,8 @@ $ git change
</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.
@@ -525,44 +429,35 @@ Do not edit or delete it.
runs <code>git</code> <code>commit</code> <code>--amend</code>.)
</p>
<h3 id="Testing">Testing</h3>
<h3 id="mail">Mail the change for review</h3>
<p>
You've <a href="code.html">written and tested your code</a>, but
before sending code out for review, run all the tests for the whole
tree to make sure the changes don't break other packages or programs:
</p>
<pre>
$ cd go/src
$ ./all.bash
</pre>
<p>
(To build under Windows use <code>all.bat</code>.)
</p>
<p>
After running for a while, the command should print
</p>
<pre>
"ALL TESTS PASSED".
</pre>
<h3 id="mail">Send the change for review</h3>
<p>
Once the change is ready, send it for review.
This is similar to a <code>git push</code> in a GitHub style workflow.
This is done via the mail alias setup earlier which despite its name, doesn't
directly mail anything, it simply sends the change to Gerrit via git push.
Once the change is ready, mail it out for review:
</p>
<pre>
$ git mail
</pre>
<p>
You can specify a reviewer or CC interested parties
using the <code>-r</code> or <code>-cc</code> options.
Both accept a comma-separated list of email addresses:
</p>
<pre>
$ git mail -r joe@golang.org -cc mabel@example.com,math-nuts@swtch.com
</pre>
<p>
Unless explicitly told otherwise, such as in the discussion leading
up to sending in the change list, it's better not to specify a reviewer.
All changes are automatically CC'ed to the
<a href="https://groups.google.com/group/golang-codereviews">golang-codereviews@googlegroups.com</a>
mailing list. If this is your first ever change, there may be a moderation
delay before it appears on the mailing list, to prevent spam.
</p>
<p>
(In Git terms, <code>git</code> <code>mail</code> pushes the local committed
changes to Gerrit using <code>git</code> <code>push</code> <code>origin</code>
@@ -584,76 +479,7 @@ remote: New Changes:
remote: https://go-review.googlesource.com/99999 math: improved Sin, Cos and Tan precision for very large arguments
</pre>
<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>
<h3 id="review">Reviewing code</h3>
<p>
Running <code>git</code> <code>mail</code> will send an email to you and the
@@ -665,15 +491,7 @@ You must reply through the web interface.
(Unlike with the old Rietveld review system, replying by mail has no effect.)
</p>
<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>
<h3 id="revise">Revise and upload</h3>
<p>
You must respond to review comments through the web interface.
@@ -716,8 +534,6 @@ $ git sync
<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.
@@ -793,8 +609,8 @@ might turn up:
<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>
@@ -823,13 +639,10 @@ restore the change commit.
<h3 id="download">Reviewing code by others</h3>
<p>
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.
You can import a change 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>
@@ -840,11 +653,11 @@ $ git fetch https://go.googlesource.com/review refs/changes/21/1221/1 &amp;&amp;
To revert, change back to the branch you were working in.
</p>
<h2 id="submit">Apply the change to the master branch</h2>
<h3 id="submit">Submit the change after the review</h3>
<p>
After the code has been <code>LGTM</code>'ed, an approver may
apply it to the master branch using the Gerrit UI.
submit 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>
@@ -856,13 +669,41 @@ and the code review will be updated with a link to the change
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>
<h2 id="more">More information</h2>
<h3 id="more">More information</h3>
<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 2016 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>

View File

@@ -4,8 +4,7 @@
}-->
<p><i>
This applies to the standard toolchain (the <code>gc</code> Go
compiler and tools). Gccgo has native gdb support.
This applies to the <code>gc</code> toolchain. Gccgo has native gdb support.
Besides this overview you might want to consult the
<a href="http://sourceware.org/gdb/current/onlinedocs/gdb/">GDB manual</a>.
</i></p>
@@ -50,14 +49,6 @@ when debugging, pass the flags <code>-gcflags "-N -l"</code> to the
debugged.
</p>
<p>
If you want to use gdb to inspect a core dump, you can trigger a dump
on a program crash, on systems that permit it, by setting
<code>GOTRACEBACK=crash</code> in the environment (see the
<a href="/pkg/runtime/#hdr-Environment_Variables"> runtime package
documentation</a> for more info).
</p>
<h3 id="Common_Operations">Common Operations</h3>
<ul>
@@ -139,7 +130,7 @@ the DWARF code.
<p>
If you're interested in what the debugging information looks like, run
'<code>objdump -W a.out</code>' and browse through the <code>.debug_*</code>
'<code>objdump -W 6.out</code>' and browse through the <code>.debug_*</code>
sections.
</p>
@@ -386,9 +377,7 @@ $3 = struct hchan&lt;*testing.T&gt;
</pre>
<p>
That <code>struct hchan&lt;*testing.T&gt;</code> is the
runtime-internal representation of a channel. It is currently empty,
or gdb would have pretty-printed its contents.
That <code>struct hchan&lt;*testing.T&gt;</code> is the runtime-internal representation of a channel. It is currently empty, or gdb would have pretty-printed it's contents.
</p>
<p>

View File

@@ -30,39 +30,6 @@ to fix critical security problems in both Go 1.4 and Go 1.5 as they arise.
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>
<p>
go1.8.2 (released 2017/05/23) includes a security fix to the
<code>crypto/elliptic</code> package.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.2">Go
1.8.2 milestone</a> on our issue tracker for details.
</p>
<p>
go1.8.3 (released 2017/05/24) includes fixes to the compiler, runtime,
documentation, and the <code>database/sql</code> package.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.3">Go
1.8.3 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.7">go1.7 (released 2016/08/15)</h2>
<p>
@@ -102,20 +69,6 @@ See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.7.4">Go
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>
<p>
go1.7.6 (released 2017/05/23) includes the same security fix as Go 1.8.2 and
was released at the same time.
See the <a href="https://github.com/golang/go/issues?q=milestone%3AGo1.8.2">Go
1.8.2 milestone</a> on our issue tracker for details.
</p>
<h2 id="go1.6">go1.6 (released 2016/02/17)</h2>
<p>

View File

@@ -52,19 +52,6 @@ user libraries. The Go 1.4 runtime is not fully merged, but that
should not be visible to Go programs.
</p>
<p>
The GCC 6 releases include a complete implementation of the Go 1.6.1
user libraries. The Go 1.6 runtime is not fully merged, but that
should not be visible to Go programs.
</p>
<p>
The GCC 7 releases are expected to include a complete implementation
of the Go 1.8 user libraries. As with earlier releases, the Go 1.8
runtime is not fully merged, but that should not be visible to Go
programs.
</p>
<h2 id="Source_code">Source code</h2>
<p>
@@ -173,6 +160,23 @@ make
make install
</pre>
<h3 id="Ubuntu">A note on Ubuntu</h3>
<p>
Current versions of Ubuntu and versions of GCC before 4.8 disagree on
where system libraries and header files are found. This is not a
gccgo issue. When building older versions of GCC, setting these
environment variables while configuring and building gccgo may fix the
problem.
</p>
<pre>
LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
C_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
CPLUS_INCLUDE_PATH=/usr/include/x86_64-linux-gnu
export LIBRARY_PATH C_INCLUDE_PATH CPLUS_INCLUDE_PATH
</pre>
<h2 id="Using_gccgo">Using gccgo</h2>
<p>
@@ -360,15 +364,12 @@ or with C++ code compiled using <code>extern "C"</code>.
<h3 id="Types">Types</h3>
<p>
Basic types map directly: an <code>int32</code> in Go is
an <code>int32_t</code> in C, an <code>int64</code> is
an <code>int64_t</code>, etc.
The Go type <code>int</code> is an integer that is the same size as a
pointer, and as such corresponds to the C type <code>intptr_t</code>.
Go <code>byte</code> is equivalent to C <code>unsigned char</code>.
Pointers in Go are pointers in C.
A Go <code>struct</code> is the same as C <code>struct</code> with the
same fields and types.
Basic types map directly: an <code>int</code> in Go is an <code>int</code>
in C, an <code>int32</code> is an <code>int32_t</code>,
etc. Go <code>byte</code> is equivalent to C <code>unsigned
char</code>.
Pointers in Go are pointers in C. A Go <code>struct</code> is the same as C
<code>struct</code> with the same fields and types.
</p>
<p>
@@ -379,7 +380,7 @@ structure (this is <b style="color: red;">subject to change</b>):
<pre>
struct __go_string {
const unsigned char *__data;
intptr_t __length;
int __length;
};
</pre>
@@ -399,8 +400,8 @@ A slice in Go is a structure. The current definition is
<pre>
struct __go_slice {
void *__values;
intptr_t __count;
intptr_t __capacity;
int __count;
int __capacity;
};
</pre>
@@ -525,3 +526,15 @@ This procedure is full of unstated caveats and restrictions and we make no
guarantee that it will not change in the future. It is more useful as a
starting point for real Go code than as a regular procedure.
</p>
<h2 id="RTEMS_Port">RTEMS Port</h2>
<p>
The gccgo compiler has been ported to <a href="http://www.rtems.com/">
<code>RTEMS</code></a>. <code>RTEMS</code> is a real-time executive
that provides a high performance environment for embedded applications
on a range of processors and embedded hardware. The current gccgo
port is for x86. The goal is to extend the port to most of the
<a href="http://www.rtems.org/wiki/index.php/SupportedCPUs">
architectures supported by <code>RTEMS</code></a>. For more information on the port,
as well as instructions on how to install it, please see this
<a href="http://www.rtems.org/wiki/index.php/GCCGoRTEMS"><code>RTEMS</code> Wiki page</a>.

View File

@@ -15,7 +15,12 @@ Do not send CLs removing the interior tags from such phrases.
ul li { margin: 0.5em 0; }
</style>
<h2 id="introduction">Introduction to Go 1.8</h2>
<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>
<p>
The latest Go release, version 1.8, arrives six months after <a href="go1.7">Go 1.7</a>.
@@ -88,8 +93,7 @@ On OpenBSD, Go now requires OpenBSD 5.9 or later. <!-- CL 34093 -->
<p>
The Plan 9 port's networking support is now much more complete
and matches the behavior of Unix and Windows with respect to deadlines
and cancelation. For Plan 9 kernel requirements, see the
<a href="https://golang.org/wiki/Plan9">Plan 9 wiki page</a>.
and cancelation.
</p>
<p>
@@ -430,11 +434,11 @@ version of gccgo.
<h3 id="plugin">Plugins</h3>
<p>
Go now provides early support for plugins with a “<code>plugin</code>
build mode for generating plugins written in Go, and a
Go now supports a “<code>plugin</code> build mode for generating
plugins written in Go, and a
new <a href="/pkg/plugin/"><code>plugin</code></a> package for
loading such plugins at run time. Plugin support is currently only
available on Linux. Please report any issues.
loading such plugins at run time. Plugin support is only currently
available on Linux.
</p>
<h2 id="runtime">Runtime</h2>
@@ -794,9 +798,9 @@ Optimizations and minor bug fixes are not listed.
hardware support for AES-GCM is present.
</p>
<p> <!-- CL 27315, CL 35290 -->
<p> <!-- CL 27315 -->
AES-128-CBC cipher suites with SHA-256 are also
now supported, but disabled by default.
now supported.
</p>
</dd>
@@ -804,6 +808,11 @@ Optimizations and minor bug fixes are not listed.
<dl id="crypto_x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
<dd>
<p> <!-- CL 30578 -->
<a href="/pkg/crypto/x509/#SystemCertPool"><code>SystemCertPool</code></a>
is now implemented on Windows.
</p>
<p> <!-- CL 24743 -->
PSS signatures are now supported.
</p>
@@ -854,12 +863,11 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
<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 <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>.
on the <code>Context</code> then passing that <code>Context</code> to
<a href="/pkg/database/sql#DB.BeginContext"><code>DB.BeginContext</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
by setting <a href="/pkg/database/sql/#TxOptions.ReadOnly"><code>TxOptions.ReadOnly</code></a>
to true.
with <a href="/pkg/database/sql/#ReadOnlyContext"><code>ReadOnlyContext</code></a>.
</p>
<p>
Queries now expose the SQL column type information for drivers that support it.
@@ -1304,7 +1312,7 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
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>
@@ -1609,9 +1617,9 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
June 31 and July 32.
</p>
<p> <!-- CL 33029 --> <!-- CL 34816 -->
<p> <!-- CL 33029 -->
The <code>tzdata</code> database has been updated to version
2016j for systems that don't already have a local time zone
2016i for systems that don't already have a local time zone
database.
</p>
@@ -1641,17 +1649,6 @@ crypto/x509: return error for missing SerialNumber (CL 27238)
and only the overall execution of the test binary would fail.
</p>
<p><!-- CL 32455 -->
The signature of the
<a href="/pkg/testing/#MainStart"><code>MainStart</code></a>
function has changed, as allowed by the documentation. It is an
internal detail and not part of the Go 1 compatibility promise.
If you're not calling <code>MainStart</code> directly but see
errors, that likely means you set the
normally-empty <code>GOROOT</code> environment variable and it
doesn't match the version of your <code>go</code> command's binary.
</p>
</dd>
</dl>

View File

@@ -143,13 +143,10 @@ packaged Go distribution.
<p>
To build a bootstrap tool chain from source, use
either the git branch <code>release-branch.go1.4</code> or
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20170531.tar.gz">go1.4-bootstrap-20170531.tar.gz</a>,
<a href="https://storage.googleapis.com/golang/go1.4-bootstrap-20161024.tar.gz">go1.4-bootstrap-20161024.tar.gz</a>,
which contains the Go 1.4 source code plus accumulated fixes
to keep the tools running on newer operating systems.
(Go 1.4 was the last distribution in which the tool chain was written in C.)
After unpacking the Go 1.4 source, <code>cd</code> to
the <code>src</code> subdirectory and run <code>make.bash</code> (or,
on Windows, <code>make.bat</code>).
</p>
<p>
@@ -221,7 +218,7 @@ To build without <code>cgo</code>, set the environment variable
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.8.1</code>, for example):</p>
(<code class="versionTag">go1.7.4</code>, for example):</p>
<pre>
$ git clone https://go.googlesource.com/go
@@ -409,7 +406,7 @@ New releases are announced on the
<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.8.1</code>.
<code class="versionTag">go1.7.4</code>.
</p>
<p>

View File

@@ -250,7 +250,7 @@ $ <b>cd $HOME/go/src/hello</b>
$ <b>go build</b>
</pre>
<pre class="testWindows">
<pre class="testWindows" style="display: none">
C:\&gt; <b>cd %USERPROFILE%\go\src\hello</b>
C:\Users\Gopher\go\src\hello&gt; <b>go build</b>
</pre>
@@ -267,7 +267,7 @@ $ <b>./hello</b>
hello, world
</pre>
<pre class="testWindows">
<pre class="testWindows" style="display: none">
C:\Users\Gopher\go\src\hello&gt; <b>hello</b>
hello, world
</pre>

View File

@@ -73,7 +73,7 @@ func test18146(t *testing.T) {
}
runtime.GOMAXPROCS(threads)
argv := append(os.Args, "-test.run=NoSuchTestExists")
if err := syscall.Exec(os.Args[0], argv, os.Environ()); err != nil {
if err := syscall.Exec(os.Args[0], argv, nil); err != nil {
t.Fatal(err)
}
}

View File

@@ -17,7 +17,7 @@ package cgotest
static stack_t oss;
static char signalStack[SIGSTKSZ];
static void changeSignalStack(void) {
static void changeSignalStack() {
stack_t ss;
memset(&ss, 0, sizeof ss);
ss.ss_sp = signalStack;
@@ -29,7 +29,7 @@ static void changeSignalStack(void) {
}
}
static void restoreSignalStack(void) {
static void restoreSignalStack() {
#if (defined(__x86_64__) || defined(__i386__)) && defined(__APPLE__)
// The Darwin C library enforces a minimum that the kernel does not.
// This is OK since we allocated this much space in mpreinit,
@@ -42,7 +42,7 @@ static void restoreSignalStack(void) {
}
}
static int zero(void) {
static int zero() {
return 0;
}
*/

View File

@@ -179,13 +179,6 @@ if test "$output" != "PASS"; then
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

View File

@@ -1,46 +0,0 @@
// 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 (
"iface_i"
"log"
"plugin"
)
func main() {
a, err := plugin.Open("iface_a.so")
if err != nil {
log.Fatalf(`plugin.Open("iface_a.so"): %v`, err)
}
b, err := plugin.Open("iface_b.so")
if err != nil {
log.Fatalf(`plugin.Open("iface_b.so"): %v`, err)
}
af, err := a.Lookup("F")
if err != nil {
log.Fatalf(`a.Lookup("F") failed: %v`, err)
}
bf, err := b.Lookup("F")
if err != nil {
log.Fatalf(`b.Lookup("F") failed: %v`, err)
}
if af.(func() interface{})() != bf.(func() interface{})() {
panic("empty interfaces not equal")
}
ag, err := a.Lookup("G")
if err != nil {
log.Fatalf(`a.Lookup("G") failed: %v`, err)
}
bg, err := b.Lookup("G")
if err != nil {
log.Fatalf(`b.Lookup("G") failed: %v`, err)
}
if ag.(func() iface_i.I)() != bg.(func() iface_i.I)() {
panic("nonempty interfaces not equal")
}
}

View File

@@ -1,17 +0,0 @@
// 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 "iface_i"
//go:noinline
func F() interface{} {
return (*iface_i.T)(nil)
}
//go:noinline
func G() iface_i.I {
return (*iface_i.T)(nil)
}

View File

@@ -1,17 +0,0 @@
// 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 "iface_i"
//go:noinline
func F() interface{} {
return (*iface_i.T)(nil)
}
//go:noinline
func G() iface_i.I {
return (*iface_i.T)(nil)
}

View File

@@ -1,17 +0,0 @@
// 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 iface_i
type I interface {
M()
}
type T struct {
}
func (t *T) M() {
}
// *T implements I

View File

@@ -1,13 +0,0 @@
// 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 dynamodbstreamsevt
import "encoding/json"
var foo json.RawMessage
type Event struct{}
func (e *Event) Dummy() {}

View File

@@ -1,31 +0,0 @@
// 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.
// The bug happened like this:
// 1) The main binary adds an itab for *json.UnsupportedValueError / error
// (concrete type / interface type). This itab goes in hash bucket 0x111.
// 2) The plugin adds that same itab again. That makes a cycle in the itab
// chain rooted at hash bucket 0x111.
// 3) The main binary then asks for the itab for *dynamodbstreamsevt.Event /
// json.Unmarshaler. This itab happens to also live in bucket 0x111.
// The lookup code goes into an infinite loop searching for this itab.
// The code is carefully crafted so that the two itabs are both from the
// same bucket, and so that the second itab doesn't exist in
// the itab hashmap yet (so the entire linked list must be searched).
package main
import (
"encoding/json"
"issue18676/dynamodbstreamsevt"
"plugin"
)
func main() {
plugin.Open("plugin.so")
var x interface{} = (*dynamodbstreamsevt.Event)(nil)
if _, ok := x.(json.Unmarshaler); !ok {
println("something")
}
}

View File

@@ -1,11 +0,0 @@
// 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 "C"
import "issue18676/dynamodbstreamsevt"
func F(evt *dynamodbstreamsevt.Event) {}

View File

@@ -15,8 +15,8 @@ goos=$(go env GOOS)
goarch=$(go env GOARCH)
function cleanup() {
rm -f plugin*.so unnamed*.so iface*.so
rm -rf host pkg sub iface issue18676
rm -f plugin*.so unnamed*.so
rm -rf host pkg sub
}
trap cleanup EXIT
@@ -32,15 +32,3 @@ GOPATH=$(pwd) go build -buildmode=plugin unnamed2.go
GOPATH=$(pwd) go build host
LD_LIBRARY_PATH=$(pwd) ./host
# Test that types and itabs get properly uniqified.
GOPATH=$(pwd) go build -buildmode=plugin iface_a
GOPATH=$(pwd) go build -buildmode=plugin iface_b
GOPATH=$(pwd) go build iface
LD_LIBRARY_PATH=$(pwd) ./iface
# Test for issue 18676 - make sure we don't add the same itab twice.
# The buggy code hangs forever, so use a timeout to check for that.
GOPATH=$(pwd) go build -buildmode=plugin -o plugin.so src/issue18676/plugin.go
GOPATH=$(pwd) go build -o issue18676 src/issue18676/main.go
timeout 10s ./issue18676

View File

@@ -1,12 +0,0 @@
// 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.
// This program segfaulted during libpreinit when built with -msan:
// http://golang.org/issue/18707
package main
import "C"
func main() {}

View File

@@ -68,25 +68,6 @@ fi
status=0
testmsanshared() {
goos=$(go env GOOS)
suffix="-installsuffix testsanitizers"
libext="so"
if [ "$goos" == "darwin" ]; then
libext="dylib"
fi
go build -msan -buildmode=c-shared $suffix -o ${TMPDIR}/libmsanshared.$libext msan_shared.go
echo 'int main() { return 0; }' > ${TMPDIR}/testmsanshared.c
$CC $(go env GOGCCFLAGS) -fsanitize=memory -o ${TMPDIR}/testmsanshared ${TMPDIR}/testmsanshared.c ${TMPDIR}/libmsanshared.$libext
if ! LD_LIBRARY_PATH=. ${TMPDIR}/testmsanshared; then
echo "FAIL: msan_shared"
status=1
fi
rm -f ${TMPDIR}/{testmsanshared,testmsanshared.c,libmsanshared.$libext}
}
if test "$msan" = "yes"; then
if ! go build -msan std; then
echo "FAIL: build -msan std"
@@ -127,8 +108,6 @@ if test "$msan" = "yes"; then
echo "FAIL: msan_fail"
status=1
fi
testmsanshared
fi
if test "$tsan" = "yes"; then

View File

@@ -815,14 +815,3 @@ func TestImplicitInclusion(t *testing.T) {
goCmd(t, "install", "-linkshared", "implicitcmd")
run(t, "running executable linked against library that contains same package as it", "./bin/implicitcmd")
}
// Tests to make sure that the type fields of empty interfaces and itab
// fields of nonempty interfaces are unique even across modules,
// so that interface equality works correctly.
func TestInterface(t *testing.T) {
goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_a")
// Note: iface_i gets installed implicitly as a dependency of iface_a.
goCmd(t, "install", "-buildmode=shared", "-linkshared", "iface_b")
goCmd(t, "install", "-linkshared", "iface")
run(t, "running type/itab uniqueness tester", "./bin/iface")
}

View File

@@ -5,8 +5,6 @@ import (
"reflect"
)
var SlicePtr interface{} = &[]int{}
var V int = 1
var HasMask []string = []string{"hi"}

View File

@@ -19,8 +19,6 @@ func F() *C {
return nil
}
var slicePtr interface{} = &[]int{}
func main() {
defer depBase.ImplementedInAsm()
// This code below causes various go.itab.* symbols to be generated in
@@ -34,11 +32,4 @@ func main() {
if reflect.TypeOf(F).Out(0) != reflect.TypeOf(c) {
panic("bad reflection results, see golang.org/issue/18252")
}
sp := reflect.New(reflect.TypeOf(slicePtr).Elem())
s := sp.Interface()
if reflect.TypeOf(s) != reflect.TypeOf(slicePtr) {
panic("bad reflection results, see golang.org/issue/18729")
}
}

View File

@@ -1,17 +0,0 @@
// 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 "iface_a"
import "iface_b"
func main() {
if iface_a.F() != iface_b.F() {
panic("empty interfaces not equal")
}
if iface_a.G() != iface_b.G() {
panic("non-empty interfaces not equal")
}
}

View File

@@ -1,17 +0,0 @@
// 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 iface_a
import "iface_i"
//go:noinline
func F() interface{} {
return (*iface_i.T)(nil)
}
//go:noinline
func G() iface_i.I {
return (*iface_i.T)(nil)
}

View File

@@ -1,17 +0,0 @@
// 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 iface_b
import "iface_i"
//go:noinline
func F() interface{} {
return (*iface_i.T)(nil)
}
//go:noinline
func G() iface_i.I {
return (*iface_i.T)(nil)
}

View File

@@ -1,17 +0,0 @@
// 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 iface_i
type I interface {
M()
}
type T struct {
}
func (t *T) M() {
}
// *T implements I

View File

@@ -99,7 +99,7 @@ func main() {
// Approximately 1 in a 100 binaries fail to start. If it happens,
// try again. These failures happen for several reasons beyond
// our control, but all of them are safe to retry as they happen
// before lldb encounters the initial SIGUSR2 stop. As we
// before lldb encounters the initial getwd breakpoint. As we
// know the tests haven't started, we are not hiding flaky tests
// with this retry.
for i := 0; i < 5; i++ {
@@ -204,11 +204,6 @@ func run(bin string, args []string) (err error) {
var opts options
opts, args = parseArgs(args)
// Pass the suffix for the current working directory as the
// first argument to the test. For iOS, cmd/go generates
// special handling of this argument.
args = append([]string{"cwdSuffix=" + pkgpath}, args...)
// ios-deploy invokes lldb to give us a shell session with the app.
s, err := newSession(appdir, args, opts)
if err != nil {
@@ -229,7 +224,6 @@ func run(bin string, args []string) (err error) {
s.do(`process handle SIGHUP --stop false --pass true --notify false`)
s.do(`process handle SIGPIPE --stop false --pass true --notify false`)
s.do(`process handle SIGUSR1 --stop false --pass true --notify false`)
s.do(`process handle SIGUSR2 --stop true --pass false --notify true`) // sent by test harness
s.do(`process handle SIGCONT --stop false --pass true --notify false`)
s.do(`process handle SIGSEGV --stop false --pass true --notify false`) // does not work
s.do(`process handle SIGBUS --stop false --pass true --notify false`) // does not work
@@ -242,9 +236,20 @@ func run(bin string, args []string) (err error) {
return nil
}
s.do(`breakpoint set -n getwd`) // in runtime/cgo/gcc_darwin_arm.go
started = true
s.doCmd("run", "stop reason = signal SIGUSR2", 20*time.Second)
s.doCmd("run", "stop reason = breakpoint", 20*time.Second)
// Move the current working directory into the faux gopath.
if pkgpath != "src" {
s.do(`breakpoint delete 1`)
s.do(`expr char* $mem = (char*)malloc(512)`)
s.do(`expr $mem = (char*)getwd($mem, 512)`)
s.do(`expr $mem = (char*)strcat($mem, "/` + pkgpath + `")`)
s.do(`call (void)chdir($mem)`)
}
startTestsLen := s.out.Len()
fmt.Fprintln(s.in, `process continue`)
@@ -515,11 +520,13 @@ func copyLocalData(dstbase string) (pkgpath string, err error) {
// Copy timezone file.
//
// Apps have the zoneinfo.zip in the root of their app bundle,
// Typical apps have the zoneinfo.zip in the root of their app bundle,
// read by the time package as the working directory at initialization.
// As we move the working directory to the GOROOT pkg directory, we
// install the zoneinfo.zip file in the pkgpath.
if underGoRoot {
err := cp(
dstbase,
filepath.Join(dstbase, pkgpath),
filepath.Join(cwd, "lib", "time", "zoneinfo.zip"),
)
if err != nil {

View File

@@ -27,5 +27,4 @@ func Init() {
gc.Thearch.SSAMarkMoves = ssaMarkMoves
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
gc.Thearch.ZeroAuto = zeroAuto
}

View File

@@ -166,27 +166,6 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64, ax *uint32, x0 *uin
return p
}
func zeroAuto(n *gc.Node, pp *obj.Prog) {
// Note: this code must not clobber any registers.
op := x86.AMOVQ
if gc.Widthptr == 4 {
op = x86.AMOVL
}
sym := gc.Linksym(n.Sym)
size := n.Type.Size()
for i := int64(0); i < size; i += int64(gc.Widthptr) {
p := gc.AddAsmAfter(op, pp)
pp = p
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = x86.REG_SP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop() {
// This is actually not the x86 NOP anymore,
// but at the point where it gets used, AX is dead

View File

@@ -21,5 +21,4 @@ func Init() {
gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
gc.Thearch.ZeroAuto = zeroAuto
}

View File

@@ -92,27 +92,6 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64, r0 *uint32) *obj.Pr
return p
}
func zeroAuto(n *gc.Node, pp *obj.Prog) {
// Note: this code must not clobber any registers.
sym := gc.Linksym(n.Sym)
size := n.Type.Size()
p := gc.Prog(arm.AMOVW)
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_REG
p.To.Reg = arm.REGTMP
for i := int64(0); i < size; i += 4 {
p := gc.AddAsmAfter(arm.AMOVW, pp)
pp = p
p.From.Type = obj.TYPE_REG
p.From.Reg = arm.REGTMP
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = arm.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop() {
p := gc.Prog(arm.AAND)

View File

@@ -21,5 +21,4 @@ func Init() {
gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
gc.Thearch.ZeroAuto = zeroAuto
}

View File

@@ -103,23 +103,6 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
return p
}
func zeroAuto(n *gc.Node, pp *obj.Prog) {
// Note: this code must not clobber any registers.
sym := gc.Linksym(n.Sym)
size := n.Type.Size()
for i := int64(0); i < size; i += 8 {
p := gc.AddAsmAfter(arm64.AMOVD, pp)
pp = p
p.From.Type = obj.TYPE_REG
p.From.Reg = arm64.REGZERO
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = arm64.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop() {
p := gc.Prog(arm64.AHINT)
p.From.Type = obj.TYPE_CONST

View File

@@ -303,9 +303,7 @@ func genhash(sym *Sym, t *Type) {
typecheckslice(fn.Nbody.Slice(), Etop)
Curfn = nil
popdcl()
if debug_dclstack != 0 {
testdclstack()
}
testdclstack()
// Disable safemode while compiling this code: the code we
// generate internally can refer to unsafe.Pointer.
@@ -495,9 +493,7 @@ func geneq(sym *Sym, t *Type) {
typecheckslice(fn.Nbody.Slice(), Etop)
Curfn = nil
popdcl()
if debug_dclstack != 0 {
testdclstack()
}
testdclstack()
// Disable safemode while compiling this code: the code we
// generate internally can refer to unsafe.Pointer.

View File

@@ -217,9 +217,7 @@ func Import(in *bufio.Reader) {
typecheckok = tcok
resumecheckwidth()
if debug_dclstack != 0 {
testdclstack()
}
testdclstack() // debugging only
}
func formatErrorf(format string, args ...interface{}) {

View File

@@ -477,10 +477,6 @@ func escAnalyze(all []*Node, recursive bool) {
for _, n := range all {
if n.Op == ODCLFUNC {
n.Esc = EscFuncPlanned
if Debug['m'] > 3 {
Dump("escAnalyze", n)
}
}
}
@@ -1679,10 +1675,7 @@ func (e *EscState) escflows(dst, src *Node, why *EscStep) {
}
// Don't bother building a graph for scalars.
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)
}
if src.Type != nil && !haspointers(src.Type) {
return
}

View File

@@ -361,12 +361,6 @@ type Arch struct {
// SSAGenBlock emits end-of-block Progs. SSAGenValue should be called
// for all values in the block before SSAGenBlock.
SSAGenBlock func(s *SSAGenState, b, next *ssa.Block)
// ZeroAuto emits code to zero the given auto stack variable.
// Code is added immediately after pp.
// ZeroAuto must not use any non-temporary registers.
// ZeroAuto will only be called for variables which contain a pointer.
ZeroAuto func(n *Node, pp *obj.Prog)
}
var pcloc int32

View File

@@ -72,15 +72,6 @@ func Appendpp(p *obj.Prog, as obj.As, ftype obj.AddrType, freg int16, foffset in
return q
}
func AddAsmAfter(as obj.As, p *obj.Prog) *obj.Prog {
q := Ctxt.NewProg()
Clearp(q)
q.As = as
q.Link = p.Link
p.Link = q
return q
}
func ggloblnod(nam *Node) {
s := Linksym(nam.Sym)
s.Gotype = Linksym(ngotype(nam))

View File

@@ -30,12 +30,11 @@ var (
)
var (
Debug_append int
Debug_closure int
debug_dclstack int
Debug_panic int
Debug_slice int
Debug_wb int
Debug_append int
Debug_closure int
Debug_panic int
Debug_slice int
Debug_wb int
)
// Debug arguments.
@@ -49,7 +48,6 @@ var debugtab = []struct {
{"append", &Debug_append}, // print information about append compilation
{"closure", &Debug_closure}, // print information about closure compilation
{"disablenil", &disable_checknil}, // disable nil checks
{"dclstack", &debug_dclstack}, // run internal dclstack checks
{"gcprog", &Debug_gcprog}, // print dump of GC programs
{"nil", &Debug_checknil}, // print information about nil checks
{"panic", &Debug_panic}, // do not hide any compiler panic
@@ -327,6 +325,7 @@ func Main() {
timings.Stop()
timings.AddEvent(int64(lexlineno-lexlineno0), "lines")
testdclstack()
mkpackage(localpkg.Name) // final import not used checks
finishUniverse()

View File

@@ -34,7 +34,6 @@ func parseFile(filename string) {
}
if nsyntaxerrors == 0 {
// Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
testdclstack()
}
}

View File

@@ -120,30 +120,7 @@ func Gvarlive(n *Node) {
}
func removevardef(firstp *obj.Prog) {
// At VARKILLs, zero variable if it is ambiguously live.
// After the VARKILL anything this variable references
// might be collected. If it were to become live again later,
// the GC will see references to already-collected objects.
// See issue 20029.
for p := firstp; p != nil; p = p.Link {
if p.As != obj.AVARKILL {
continue
}
n := p.To.Node.(*Node)
if !n.Name.Needzero {
continue
}
if n.Class != PAUTO {
Fatalf("zero of variable which isn't PAUTO %v", n)
}
if n.Type.Size()%int64(Widthptr) != 0 {
Fatalf("zero of variable not a multiple of ptr size %v", n)
}
Thearch.ZeroAuto(n, p)
}
for p := firstp; p != nil; p = p.Link {
for p.Link != nil && (p.Link.As == obj.AVARDEF || p.Link.As == obj.AVARKILL || p.Link.As == obj.AVARLIVE) {
p.Link = p.Link.Link
}

View File

@@ -585,7 +585,7 @@ func isliteral(n *Node) bool {
}
func (n *Node) isSimpleName() bool {
return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP && n.Class != PEXTERN
return n.Op == ONAME && n.Addable && n.Class != PAUTOHEAP
}
func litas(l *Node, r *Node, init *Nodes) {

View File

@@ -3470,13 +3470,8 @@ func (s *state) insertWBstore(t *Type, left, right *ssa.Value, line int32, skip
if s.WBLineno == 0 {
s.WBLineno = left.Line
}
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)
}
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

View File

@@ -63,9 +63,6 @@ func TestArithmeticConst(t *testing.T) { runTest(t, "arithConst.go") }
func TestChan(t *testing.T) { runTest(t, "chan.go") }
// TestComparisonsConst tests results for comparison operations against constants.
func TestComparisonsConst(t *testing.T) { runTest(t, "cmpConst.go") }
func TestCompound(t *testing.T) { runTest(t, "compound.go") }
func TestCtl(t *testing.T) { runTest(t, "ctl.go") }

View File

@@ -1833,9 +1833,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
funcbody(fn)
Curfn = fn
popdcl()
if debug_dclstack != 0 {
testdclstack()
}
testdclstack()
// wrappers where T is anonymous (struct or interface) can be duplicated.
if rcvr.IsStruct() || rcvr.IsInterface() || rcvr.IsPtr() && rcvr.Elem().IsStruct() {

View File

@@ -488,17 +488,6 @@ func testLrot() {
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 {

File diff suppressed because it is too large Load Diff

View File

@@ -1,248 +0,0 @@
// 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.
// This program generates a test to verify that the standard comparison
// operators properly handle one const operand. The test file should be
// generated with a known working version of go.
// launch with `go run cmpConstGen.go` a file called cmpConst.go
// will be written into the parent directory containing the tests
package main
import (
"bytes"
"fmt"
"go/format"
"io/ioutil"
"log"
"math/big"
"sort"
)
const (
maxU64 = (1 << 64) - 1
maxU32 = (1 << 32) - 1
maxU16 = (1 << 16) - 1
maxU8 = (1 << 8) - 1
maxI64 = (1 << 63) - 1
maxI32 = (1 << 31) - 1
maxI16 = (1 << 15) - 1
maxI8 = (1 << 7) - 1
minI64 = -(1 << 63)
minI32 = -(1 << 31)
minI16 = -(1 << 15)
minI8 = -(1 << 7)
)
func cmp(left *big.Int, op string, right *big.Int) bool {
switch left.Cmp(right) {
case -1: // less than
return op == "<" || op == "<=" || op == "!="
case 0: // equal
return op == "==" || op == "<=" || op == ">="
case 1: // greater than
return op == ">" || op == ">=" || op == "!="
}
panic("unexpected comparison value")
}
func inRange(typ string, val *big.Int) bool {
min, max := &big.Int{}, &big.Int{}
switch typ {
case "uint64":
max = max.SetUint64(maxU64)
case "uint32":
max = max.SetUint64(maxU32)
case "uint16":
max = max.SetUint64(maxU16)
case "uint8":
max = max.SetUint64(maxU8)
case "int64":
min = min.SetInt64(minI64)
max = max.SetInt64(maxI64)
case "int32":
min = min.SetInt64(minI32)
max = max.SetInt64(maxI32)
case "int16":
min = min.SetInt64(minI16)
max = max.SetInt64(maxI16)
case "int8":
min = min.SetInt64(minI8)
max = max.SetInt64(maxI8)
default:
panic("unexpected type")
}
return cmp(min, "<=", val) && cmp(val, "<=", max)
}
func getValues(typ string) []*big.Int {
Uint := func(v uint64) *big.Int { return big.NewInt(0).SetUint64(v) }
Int := func(v int64) *big.Int { return big.NewInt(0).SetInt64(v) }
values := []*big.Int{
// limits
Uint(maxU64),
Uint(maxU64 - 1),
Uint(maxI64 + 1),
Uint(maxI64),
Uint(maxI64 - 1),
Uint(maxU32 + 1),
Uint(maxU32),
Uint(maxU32 - 1),
Uint(maxI32 + 1),
Uint(maxI32),
Uint(maxI32 - 1),
Uint(maxU16 + 1),
Uint(maxU16),
Uint(maxU16 - 1),
Uint(maxI16 + 1),
Uint(maxI16),
Uint(maxI16 - 1),
Uint(maxU8 + 1),
Uint(maxU8),
Uint(maxU8 - 1),
Uint(maxI8 + 1),
Uint(maxI8),
Uint(maxI8 - 1),
Uint(0),
Int(minI8 + 1),
Int(minI8),
Int(minI8 - 1),
Int(minI16 + 1),
Int(minI16),
Int(minI16 - 1),
Int(minI32 + 1),
Int(minI32),
Int(minI32 - 1),
Int(minI64 + 1),
Int(minI64),
// other possibly interesting values
Uint(1),
Int(-1),
Uint(0xff << 56),
Uint(0xff << 32),
Uint(0xff << 24),
}
sort.Slice(values, func(i, j int) bool { return values[i].Cmp(values[j]) == -1 })
var ret []*big.Int
for _, val := range values {
if !inRange(typ, val) {
continue
}
ret = append(ret, val)
}
return ret
}
func sigString(v *big.Int) string {
var t big.Int
t.Abs(v)
if v.Sign() == -1 {
return "neg" + t.String()
}
return t.String()
}
func main() {
types := []string{
"uint64", "uint32", "uint16", "uint8",
"int64", "int32", "int16", "int8",
}
w := new(bytes.Buffer)
fmt.Fprintf(w, "// run\n")
fmt.Fprintf(w, "// Code generated by gen/cmpConstGen.go. DO NOT EDIT.\n\n")
fmt.Fprintf(w, "package main;\n")
fmt.Fprintf(w, "import (\"fmt\"; \"reflect\"; \"runtime\";)\n")
fmt.Fprintf(w, "// results show the expected result for the elements left of, equal to and right of the index.\n")
fmt.Fprintf(w, "type result struct{l, e, r bool}\n")
fmt.Fprintf(w, "var (\n")
fmt.Fprintf(w, " eq = result{l: false, e: true, r: false}\n")
fmt.Fprintf(w, " ne = result{l: true, e: false, r: true}\n")
fmt.Fprintf(w, " lt = result{l: true, e: false, r: false}\n")
fmt.Fprintf(w, " le = result{l: true, e: true, r: false}\n")
fmt.Fprintf(w, " gt = result{l: false, e: false, r: true}\n")
fmt.Fprintf(w, " ge = result{l: false, e: true, r: true}\n")
fmt.Fprintf(w, ")\n")
operators := []struct{ op, name string }{
{"<", "lt"},
{"<=", "le"},
{">", "gt"},
{">=", "ge"},
{"==", "eq"},
{"!=", "ne"},
}
for _, typ := range types {
// generate a slice containing valid values for this type
fmt.Fprintf(w, "\n// %v tests\n", typ)
values := getValues(typ)
fmt.Fprintf(w, "var %v_vals = []%v{\n", typ, typ)
for _, val := range values {
fmt.Fprintf(w, "%v,\n", val.String())
}
fmt.Fprintf(w, "}\n")
// generate test functions
for _, r := range values {
// TODO: could also test constant on lhs.
sig := sigString(r)
for _, op := range operators {
// no need for go:noinline because the function is called indirectly
fmt.Fprintf(w, "func %v_%v_%v(x %v) bool { return x %v %v; }\n", op.name, sig, typ, typ, op.op, r.String())
}
}
// generate a table of test cases
fmt.Fprintf(w, "var %v_tests = []struct{\n", typ)
fmt.Fprintf(w, " idx int // index of the constant used\n")
fmt.Fprintf(w, " exp result // expected results\n")
fmt.Fprintf(w, " fn func(%v) bool\n", typ)
fmt.Fprintf(w, "}{\n")
for i, r := range values {
sig := sigString(r)
for _, op := range operators {
fmt.Fprintf(w, "{idx: %v,", i)
fmt.Fprintf(w, "exp: %v,", op.name)
fmt.Fprintf(w, "fn: %v_%v_%v},\n", op.name, sig, typ)
}
}
fmt.Fprintf(w, "}\n")
}
// emit the main function, looping over all test cases
fmt.Fprintf(w, "func main() {\n")
for _, typ := range types {
fmt.Fprintf(w, "for i, test := range %v_tests {\n", typ)
fmt.Fprintf(w, " for j, x := range %v_vals {\n", typ)
fmt.Fprintf(w, " want := test.exp.l\n")
fmt.Fprintf(w, " if j == test.idx {\nwant = test.exp.e\n}")
fmt.Fprintf(w, " else if j > test.idx {\nwant = test.exp.r\n}\n")
fmt.Fprintf(w, " if test.fn(x) != want {\n")
fmt.Fprintf(w, " fn := runtime.FuncForPC(reflect.ValueOf(test.fn).Pointer()).Name()\n")
fmt.Fprintf(w, " msg := fmt.Sprintf(\"test failed: %%v(%%v) != %%v [type=%v i=%%v j=%%v idx=%%v]\", fn, x, want, i, j, test.idx)\n", typ)
fmt.Fprintf(w, " panic(msg)\n")
fmt.Fprintf(w, " }\n")
fmt.Fprintf(w, " }\n")
fmt.Fprintf(w, "}\n")
}
fmt.Fprintf(w, "}\n")
// gofmt result
b := w.Bytes()
src, err := format.Source(b)
if err != nil {
fmt.Printf("%s\n", b)
panic(err)
}
// write to file
err = ioutil.WriteFile("../cmpConst.go", src, 0666)
if err != nil {
log.Fatalf("can't write output: %v\n", err)
}
}

View File

@@ -1107,7 +1107,7 @@ OpSwitch:
case OSLICE, OSLICE3:
ok |= Erv
n.Left = typecheck(n.Left, Erv)
n.Left = typecheck(n.Left, top)
low, high, max := n.SliceBounds()
hasmax := n.Op.IsSlice3()
low = typecheck(low, Erv)
@@ -1119,10 +1119,6 @@ OpSwitch:
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)
@@ -1135,7 +1131,12 @@ OpSwitch:
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 {

View File

@@ -57,13 +57,8 @@ func startProfile() {
Fatalf("%v", err)
}
atExit(func() {
// Profile all outstanding allocations.
runtime.GC()
// compilebench parses the memory profile to extract memstats,
// which are only written in the legacy pprof format.
// See golang.org/issue/18641 and runtime/pprof/pprof.go:writeHeap.
const writeLegacyFormat = 1
if err := pprof.Lookup("heap").WriteTo(f, writeLegacyFormat); err != nil {
runtime.GC() // profile all outstanding allocations
if err := pprof.WriteHeapProfile(f); err != nil {
Fatalf("%v", err)
}
})

View File

@@ -2071,29 +2071,6 @@ func isstack(n *Node) bool {
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 {
@@ -2104,21 +2081,15 @@ func needwritebarrier(l *Node, r *Node) bool {
return false
}
// No write barrier for write to stack.
if isstack(l) {
// No write barrier for write of non-pointers.
dowidth(l.Type)
if !haspointers(l.Type) {
return false
}
// 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) {
// No write barrier for write to stack.
if isstack(l) {
return false
}
@@ -3146,12 +3117,12 @@ func walkcompare(n *Node, init *Nodes) *Node {
cmpr = cmpr.Left
}
if !islvalue(cmpl) || !islvalue(cmpr) {
Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
}
// Chose not to inline. Call equality function directly.
if !inline {
if !islvalue(cmpl) || !islvalue(cmpr) {
Fatalf("arguments of comparison must be lvalues - %v %v", cmpl, cmpr)
}
// eq algs take pointers
pl := temp(ptrto(t))
al := nod(OAS, pl, nod(OADDR, cmpl, nil))

View File

@@ -23,5 +23,4 @@ func Init() {
gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
gc.Thearch.ZeroAuto = zeroAuto
}

View File

@@ -92,23 +92,6 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
return p
}
func zeroAuto(n *gc.Node, pp *obj.Prog) {
// Note: this code must not clobber any registers.
sym := gc.Linksym(n.Sym)
size := n.Type.Size()
for i := int64(0); i < size; i += 4 {
p := gc.AddAsmAfter(mips.AMOVW, pp)
pp = p
p.From.Type = obj.TYPE_REG
p.From.Reg = mips.REGZERO
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = mips.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop() {
p := gc.Prog(mips.ANOR)
p.From.Type = obj.TYPE_REG

View File

@@ -25,5 +25,4 @@ func Init() {
gc.Thearch.SSAMarkMoves = func(s *gc.SSAGenState, b *ssa.Block) {}
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
gc.Thearch.ZeroAuto = zeroAuto
}

View File

@@ -95,23 +95,6 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
return p
}
func zeroAuto(n *gc.Node, pp *obj.Prog) {
// Note: this code must not clobber any registers.
sym := gc.Linksym(n.Sym)
size := n.Type.Size()
for i := int64(0); i < size; i += 8 {
p := gc.AddAsmAfter(mips.AMOVV, pp)
pp = p
p.From.Type = obj.TYPE_REG
p.From.Reg = mips.REGZERO
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = mips.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop() {
p := gc.Prog(mips.ANOR)
p.From.Type = obj.TYPE_REG

View File

@@ -24,7 +24,6 @@ func Init() {
gc.Thearch.SSAMarkMoves = ssaMarkMoves
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
gc.Thearch.ZeroAuto = zeroAuto
initvariants()
initproginfo()

View File

@@ -90,23 +90,6 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
return p
}
func zeroAuto(n *gc.Node, pp *obj.Prog) {
// Note: this code must not clobber any registers.
sym := gc.Linksym(n.Sym)
size := n.Type.Size()
for i := int64(0); i < size; i += 8 {
p := gc.AddAsmAfter(ppc64.AMOVD, pp)
pp = p
p.From.Type = obj.TYPE_REG
p.From.Reg = ppc64.REGZERO
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = ppc64.REGSP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop() {
p := gc.Prog(ppc64.AOR)
p.From.Type = obj.TYPE_REG

View File

@@ -20,5 +20,4 @@ func Init() {
gc.Thearch.SSAMarkMoves = ssaMarkMoves
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
gc.Thearch.ZeroAuto = zeroAuto
}

View File

@@ -143,19 +143,6 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64) *obj.Prog {
return p
}
func zeroAuto(n *gc.Node, pp *obj.Prog) {
// Note: this code must not clobber any registers.
p := gc.AddAsmAfter(s390x.ACLEAR, pp)
pp = p
p.From.Type = obj.TYPE_CONST
p.From.Offset = n.Type.Size()
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = s390x.REGSP
p.To.Offset = n.Xoffset
p.To.Sym = gc.Linksym(n.Sym)
}
func ginsnop() {
p := gc.Prog(s390x.AOR)
p.From.Type = obj.TYPE_REG

View File

@@ -424,7 +424,7 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
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, ssa.OpS390XMOVDreg:
case ssa.OpCopy, ssa.OpS390XMOVDconvert:
if v.Type.IsMemory() {
return
}
@@ -433,11 +433,6 @@ func ssaGenValue(s *gc.SSAGenState, v *ssa.Value) {
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())

View File

@@ -294,39 +294,6 @@ func checkFunc(f *Func) {
}
}
}
// Check that if a tuple has a memory type, it is second.
for _, b := range f.Blocks {
for _, v := range b.Values {
if v.Type.IsTuple() && v.Type.FieldType(0).IsMemory() {
f.Fatalf("memory is first in a tuple: %s\n", v.LongString())
}
}
}
// Check that only one memory is live at any point.
// TODO: make this check examine interblock.
if f.scheduled {
for _, b := range f.Blocks {
var mem *Value // the live memory
for _, v := range b.Values {
if v.Op != OpPhi {
for _, a := range v.Args {
if a.Type.IsMemory() || a.Type.IsTuple() && a.Type.FieldType(1).IsMemory() {
if mem == nil {
mem = a
} else if mem != a {
f.Fatalf("two live mems @ %s: %s and %s", v, mem, a)
}
}
}
}
if v.Type.IsMemory() || v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
mem = v
}
}
}
}
}
// domCheck reports whether x dominates y (including x==y).

View File

@@ -313,13 +313,9 @@ func cmpVal(v, w *Value, auxIDs auxmap) Cmp {
// that generate memory.
return lt2Cmp(v.ID < w.ID)
}
// OpSelect is a pseudo-op. We need to be more agressive
// regarding CSE to keep multiple OpSelect's of the same
// argument from existing.
if v.Op != OpSelect0 && v.Op != OpSelect1 {
if tc := v.Type.Compare(w.Type); tc != CMPeq {
return tc
}
if tc := v.Type.Compare(w.Type); tc != CMPeq {
return tc
}
if v.Aux != w.Aux {

View File

@@ -64,7 +64,7 @@ func liveValues(f *Func, reachable []bool) []bool {
q = append(q, v)
}
for _, v := range b.Values {
if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects) && !live[v.ID] {
if opcodeTable[v.Op].call && !live[v.ID] {
live[v.ID] = true
q = append(q, v)
}

View File

@@ -6,7 +6,6 @@ package ssa
import (
"cmd/internal/obj"
"cmd/internal/obj/s390x"
"cmd/internal/obj/x86"
"testing"
)
@@ -22,10 +21,6 @@ func testConfig(t testing.TB) *Config {
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 {
@@ -35,20 +30,8 @@ type DummyFrontend struct {
func (DummyFrontend) StringData(s string) interface{} {
return nil
}
type dummyGCNode struct {
typ Type
name string
}
func (d *dummyGCNode) Typ() Type {
return d.typ
}
func (d *dummyGCNode) String() string {
return d.name
}
func (d DummyFrontend) Auto(t Type) GCNode {
return &dummyGCNode{typ: t, name: "dummy"}
func (DummyFrontend) Auto(t Type) GCNode {
return nil
}
func (d DummyFrontend) SplitString(s LocalSlot) (LocalSlot, LocalSlot) {
return LocalSlot{s.N, d.TypeBytePtr(), s.Off}, LocalSlot{s.N, d.TypeInt(), s.Off + 8}

View File

@@ -522,15 +522,15 @@ func init() {
// 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, hasSideEffects: true},
{name: "XCHGQ", argLength: 3, reg: gpstorexchg, asm: "XCHGQ", aux: "SymOff", resultInArg0: true, faultOnNilArg1: true, hasSideEffects: true},
{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},
// 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, hasSideEffects: true},
{name: "XADDQlock", argLength: 3, reg: gpstorexchg, asm: "XADDQ", typ: "(UInt64,Mem)", aux: "SymOff", resultInArg0: true, clobberFlags: true, faultOnNilArg1: true, hasSideEffects: true},
{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: "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 @@ func init() {
// 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, hasSideEffects: true},
{name: "CMPXCHGQlock", argLength: 4, reg: cmpxchg, asm: "CMPXCHGQ", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
{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},
// Atomic memory updates.
{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
{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
}
var AMD64blocks = []blockData{

View File

@@ -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> (ZeroExt16to32 x) [16-c&15]))
(Lrot8 <t> x [c]) -> (OR (SLLconst <t> x [c&7]) (SRLconst <t> (ZeroExt8to32 x) [8-c&7]))
(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]))
// constants
(Const8 [val]) -> (MOVWconst [val])

View File

@@ -529,148 +529,110 @@
// 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) && 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)
(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)
(MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVHload [off1+off2] {sym} ptr mem)
(MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVHUload [off1+off2] {sym} ptr mem)
(MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVWload [off1+off2] {sym} ptr mem)
(MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVWUload [off1+off2] {sym} ptr mem)
(MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVDload [off1+off2] {sym} ptr mem)
(FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(FMOVSload [off1+off2] {sym} ptr mem)
(FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(FMOVDload [off1+off2] {sym} ptr mem)
(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) && is32Bit(off1+off2) ->
(MOVBstore [off1+off2] {sym} ptr val mem)
(MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem) -> (MOVBstore [off1+off2] {sym} ptr val mem)
(MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVHstore [off1+off2] {sym} ptr val mem)
(MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVWstore [off1+off2] {sym} ptr val mem)
(MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVDstore [off1+off2] {sym} ptr val mem)
(FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(FMOVSstore [off1+off2] {sym} ptr val mem)
(FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(FMOVDstore [off1+off2] {sym} ptr val mem)
(MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) && is32Bit(off1+off2) ->
(MOVBstorezero [off1+off2] {sym} ptr mem)
(MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem) -> (MOVBstorezero [off1+off2] {sym} ptr mem)
(MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVHstorezero [off1+off2] {sym} ptr mem)
(MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVWstorezero [off1+off2] {sym} ptr mem)
(MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
&& is32Bit(off1+off2) && !isArg(sym)
&& ((off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isAuto(sym)) ->
&& (off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym) ->
(MOVDstorezero [off1+off2] {sym} ptr mem)
(MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) ->
(MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
(MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) ->
(MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
(MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) ->
(MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2) ->
(MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
(MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) ->
(MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2) ->
(MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
(MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem) && canMergeSym(sym1,sym2)
&& is32Bit(off1+off2) && !isArg(mergeSym(sym1,sym2))
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(mergeSym(sym1,sym2))) ->
&& ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1)) ->
(MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
// store zero

View File

@@ -456,16 +456,16 @@ func init() {
// atomic stores.
// store arg1 to arg0. arg2=mem. returns memory. auxint must be zero.
{name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true, hasSideEffects: true},
{name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: true, hasSideEffects: true},
{name: "STLR", argLength: 3, reg: gpstore, asm: "STLR", faultOnNilArg0: true},
{name: "STLRW", argLength: 3, reg: gpstore, asm: "STLRW", faultOnNilArg0: 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, hasSideEffects: true},
{name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicExchange64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
{name: "LoweredAtomicExchange32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
// atomic add.
// *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>. auxint must be zero.
@@ -473,8 +473,8 @@ func init() {
// ADD Rarg1, Rout
// STLXR Rout, (Rarg0), Rtmp
// CBNZ Rtmp, -3(PC)
{name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicAdd64", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
{name: "LoweredAtomicAdd32", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
// atomic compare and swap.
// arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory. auxint must be zero.
@@ -490,8 +490,8 @@ func init() {
// STLXR Rarg2, (Rarg0), Rtmp
// CBNZ Rtmp, -4(PC)
// CSET EQ, Rout
{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},
{name: "LoweredAtomicCas64", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true},
{name: "LoweredAtomicCas32", argLength: 4, reg: gpcas, resultNotInArgs: true, clobberFlags: true, faultOnNilArg0: true},
// atomic and/or.
// *arg0 &= (|=) arg1. arg2=mem. returns memory. auxint must be zero.
@@ -499,8 +499,8 @@ func init() {
// AND/OR Rarg1, Rtmp
// STLXRB Rtmp, (Rarg0), Rtmp
// CBNZ Rtmp, -3(PC)
{name: "LoweredAtomicAnd8", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "ORR", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicAnd8", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true},
{name: "LoweredAtomicOr8", argLength: 3, reg: gpstore, asm: "ORR", faultOnNilArg0: true},
}
blocks := []blockData{

View File

@@ -119,8 +119,8 @@ func init() {
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}, clobbers: buildReg("F15")} // int-float conversion uses F15 as tmp
gpfp = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}, clobbers: buildReg("F15")}
fpgp = regInfo{inputs: []regMask{fp}, outputs: []regMask{gp}}
gpfp = regInfo{inputs: []regMask{gp}, outputs: []regMask{fp}}
fp21 = regInfo{inputs: []regMask{fp, fp}, outputs: []regMask{fp}}
fp2flags = regInfo{inputs: []regMask{fp, fp}}
fpload = regInfo{inputs: []regMask{gpspsbg}, outputs: []regMask{fp}}

View File

@@ -404,7 +404,8 @@
(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)
(ANDconst <config.fe.TypeUInt32()> [3]
(XORconst <config.fe.TypeUInt32()> [3] ptr)))))) mem)
// AtomicOr8(ptr,val) -> LoweredAtomicOr(ptr&^3,uint32(val) << (((ptr^3) & 3) * 8))
(AtomicOr8 ptr val mem) && config.BigEndian ->

View File

@@ -267,8 +267,8 @@ func init() {
// SYNC
// MOVW Rarg1, (Rarg0)
// SYNC
{name: "LoweredAtomicStore", argLength: 3, reg: gpstore, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicStore", argLength: 3, reg: gpstore, faultOnNilArg0: true},
{name: "LoweredAtomicStorezero", argLength: 2, reg: gpstore0, faultOnNilArg0: true},
// atomic exchange.
// store arg1 to arg0. arg2=mem. returns <old content of *arg0, memory>.
@@ -278,7 +278,7 @@ func init() {
// SC Rtmp, (Rarg0)
// BEQ Rtmp, -3(PC)
// SYNC
{name: "LoweredAtomicExchange", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicExchange", argLength: 3, reg: gpxchg, resultNotInArgs: true, faultOnNilArg0: true},
// atomic add.
// *arg0 += arg1. arg2=mem. returns <new content of *arg0, memory>.
@@ -289,8 +289,8 @@ func init() {
// BEQ Rtmp, -3(PC)
// SYNC
// ADDU Rarg1, Rout
{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},
{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},
// atomic compare and swap.
// arg0 = pointer, arg1 = old value, arg2 = new value, arg3 = memory.
@@ -308,7 +308,7 @@ func init() {
// SC Rout, (Rarg0)
// BEQ Rout, -4(PC)
// SYNC
{name: "LoweredAtomicCas", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicCas", argLength: 4, reg: gpcas, resultNotInArgs: true, faultOnNilArg0: true},
// atomic and/or.
// *arg0 &= (|=) arg1. arg2=mem. returns memory.
@@ -318,8 +318,8 @@ func init() {
// SC Rtmp, (Rarg0)
// BEQ Rtmp, -3(PC)
// SYNC
{name: "LoweredAtomicAnd", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicOr", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true, hasSideEffects: true},
{name: "LoweredAtomicAnd", argLength: 3, reg: gpstore, asm: "AND", faultOnNilArg0: true},
{name: "LoweredAtomicOr", argLength: 3, reg: gpstore, asm: "OR", faultOnNilArg0: true},
// large or unaligned zeroing
// arg0 = address of memory to zero (in R1, changed as side effect)

View File

@@ -338,9 +338,9 @@
(Geq32F x y) -> (FGreaterEqual (FCMPU x y))
(Geq64F x y) -> (FGreaterEqual (FCMPU 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))
(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))
(Geq64U x y) -> (GreaterEqual (CMPU x y))
// Absorb pseudo-ops into blocks.

View File

@@ -312,12 +312,9 @@
// Lowering loads
(Load <t> ptr mem) && (is64BitInt(t) || isPtr(t)) -> (MOVDload 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) && 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) && is32BitFloat(t) -> (FMOVSload ptr mem)
(Load <t> ptr mem) && is64BitFloat(t) -> (FMOVDload ptr mem)
@@ -440,7 +437,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 <config.fe.TypeBool()> cond)) yes no)
(If cond yes no) -> (NE (CMPWconst [0] (MOVBZreg cond)) yes no)
// ***************************
// Above: lowering rules
@@ -448,28 +445,16 @@
// ***************************
// 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 -> (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)
(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
// Fold boolean tests into blocks.
(NE (CMPWconst [0] (MOVDLT (MOVDconst [0]) (MOVDconst [1]) cmp)) yes no) -> (LT cmp yes no)
@@ -537,8 +522,8 @@
(CMP (MOVDconst [c]) x) && is32Bit(c) -> (InvertFlags (CMPconst x [c]))
(CMPW x (MOVDconst [c])) -> (CMPWconst x [c])
(CMPW (MOVDconst [c]) x) -> (InvertFlags (CMPWconst x [c]))
(CMPU x (MOVDconst [c])) && isU32Bit(c) -> (CMPUconst x [int64(uint32(c))])
(CMPU (MOVDconst [c]) x) && isU32Bit(c) -> (InvertFlags (CMPUconst x [int64(uint32(c))]))
(CMPU x (MOVDconst [c])) && is32Bit(c) -> (CMPUconst x [int64(uint32(c))])
(CMPU (MOVDconst [c]) x) && is32Bit(c) -> (InvertFlags (CMPUconst x [int64(uint32(c))]))
(CMPWU x (MOVDconst [c])) -> (CMPWUconst x [int64(uint32(c))])
(CMPWU (MOVDconst [c]) x) -> (InvertFlags (CMPWUconst x [int64(uint32(c))]))
@@ -587,46 +572,46 @@
(MOVDNE x y (InvertFlags cmp)) -> (MOVDNE x y cmp)
// don't extend after proper load
(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)
(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
// don't extend if argument is already extended
(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)
(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
// fold double extensions
(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)
(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
// fold extensions into constants
(MOVBreg (MOVDconst [c])) -> (MOVDconst [int64(int8(c))])
@@ -656,10 +641,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) -> (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)
(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
// Don't extend before storing
(MOVWstore [off] {sym} ptr (MOVWreg x) mem) -> (MOVWstore [off] {sym} ptr x mem)
@@ -900,9 +885,9 @@
(MOVDEQ y _ (FlagLT)) -> y
(MOVDEQ y _ (FlagGT)) -> y
(MOVDNE y _ (FlagEQ)) -> y
(MOVDNE _ x (FlagLT)) -> x
(MOVDNE _ x (FlagGT)) -> x
(MOVDNE _ y (FlagEQ)) -> y
(MOVDNE x _ (FlagLT)) -> x
(MOVDNE x _ (FlagGT)) -> x
(MOVDLT y _ (FlagEQ)) -> y
(MOVDLT _ x (FlagLT)) -> x

View File

@@ -311,9 +311,6 @@ func init() {
{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
@@ -429,14 +426,14 @@ func init() {
// 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, hasSideEffects: true},
{name: "MOVDatomicstore", argLength: 3, reg: gpstore, asm: "MOVD", aux: "SymOff", typ: "Mem", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
{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},
// 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, hasSideEffects: true},
{name: "LAAG", argLength: 3, reg: gpstorelaa, asm: "LAAG", typ: "(UInt64,Mem)", aux: "SymOff", faultOnNilArg0: true, hasSideEffects: true},
{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: "AddTupleFirst32", argLength: 2}, // arg0=tuple <x,y>. Returns <x+arg1,y>.
{name: "AddTupleFirst64", argLength: 2}, // arg0=tuple <x,y>. Returns <x+arg1,y>.
@@ -461,13 +458,13 @@ func init() {
// 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, hasSideEffects: true},
{name: "LoweredAtomicCas64", argLength: 4, reg: cas, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
{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},
// 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, hasSideEffects: true},
{name: "LoweredAtomicExchange64", argLength: 3, reg: exchange, asm: "CSG", aux: "SymOff", clobberFlags: true, faultOnNilArg0: true, hasSideEffects: true},
{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},
// find leftmost one
{

View File

@@ -460,20 +460,20 @@ var genericOps = []opData{
// 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", 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.
{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.
}
// kind control successors implicit exit

View File

@@ -52,7 +52,6 @@ type opData struct {
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 {
@@ -209,9 +208,6 @@ func genOp() {
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

View File

@@ -33,24 +33,13 @@ type loop struct {
// 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
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()
if oldouter == nil || sdom.isAncestorEq(oldouter.header, outer.header) {
inner.outer = outer
outer.isInner = false
if inner.containsCall {
outer.setContainsCall()
}
}
}

View File

@@ -1,87 +0,0 @@
// 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()
}

View File

@@ -82,7 +82,7 @@ func nilcheckelim(f *Func) {
}
}
// Next, eliminate any redundant nil checks in this block.
// Next, process values in the block.
i := 0
for _, v := range b.Values {
b.Values[i] = v
@@ -105,10 +105,13 @@ func nilcheckelim(f *Func) {
f.Config.Warnl(v.Line, "removed nil check")
}
v.reset(OpUnknown)
// TODO: f.freeValue(v)
i--
continue
}
// Record the fact that we know ptr is non nil, and remember to
// undo that information when this dominator subtree is done.
nonNilValues[ptr.ID] = true
work = append(work, bp{op: ClearPtr, ptr: ptr})
}
}
for j := i; j < len(b.Values); j++ {
@@ -116,21 +119,6 @@ func nilcheckelim(f *Func) {
}
b.Values = b.Values[:i]
// Finally, find redundant nil checks for subsequent blocks.
// Note that we can't add these until the loop above is done, as the
// values in the block are not ordered in any way when this pass runs.
// This was the cause of issue #18725.
for _, v := range b.Values {
if v.Op != OpNilCheck {
continue
}
ptr := v.Args[0]
// Record the fact that we know ptr is non nil, and remember to
// undo that information when this dominator subtree is done.
nonNilValues[ptr.ID] = true
work = append(work, bp{op: ClearPtr, ptr: ptr})
}
// Add all dominated blocks to the work list.
for w := sdom[node.block.ID].child; w != nil; w = sdom[w.ID].sibling {
work = append(work, bp{op: Work, block: w})

View File

@@ -34,7 +34,6 @@ type opInfo struct {
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 {

View File

@@ -1473,8 +1473,6 @@ const (
OpS390XMOVHZreg
OpS390XMOVWreg
OpS390XMOVWZreg
OpS390XMOVDreg
OpS390XMOVDnop
OpS390XMOVDconst
OpS390XCFDBRA
OpS390XCGDBRA
@@ -7307,7 +7305,6 @@ var opcodeTable = [...]opInfo{
argLen: 3,
resultInArg0: true,
faultOnNilArg1: true,
hasSideEffects: true,
asm: x86.AXCHGL,
reg: regInfo{
inputs: []inputInfo{
@@ -7325,7 +7322,6 @@ var opcodeTable = [...]opInfo{
argLen: 3,
resultInArg0: true,
faultOnNilArg1: true,
hasSideEffects: true,
asm: x86.AXCHGQ,
reg: regInfo{
inputs: []inputInfo{
@@ -7344,7 +7340,6 @@ var opcodeTable = [...]opInfo{
resultInArg0: true,
clobberFlags: true,
faultOnNilArg1: true,
hasSideEffects: true,
asm: x86.AXADDL,
reg: regInfo{
inputs: []inputInfo{
@@ -7363,7 +7358,6 @@ var opcodeTable = [...]opInfo{
resultInArg0: true,
clobberFlags: true,
faultOnNilArg1: true,
hasSideEffects: true,
asm: x86.AXADDQ,
reg: regInfo{
inputs: []inputInfo{
@@ -7391,7 +7385,6 @@ var opcodeTable = [...]opInfo{
argLen: 4,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: x86.ACMPXCHGL,
reg: regInfo{
inputs: []inputInfo{
@@ -7412,7 +7405,6 @@ var opcodeTable = [...]opInfo{
argLen: 4,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: x86.ACMPXCHGQ,
reg: regInfo{
inputs: []inputInfo{
@@ -7433,7 +7425,6 @@ var opcodeTable = [...]opInfo{
argLen: 3,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: x86.AANDB,
reg: regInfo{
inputs: []inputInfo{
@@ -7448,7 +7439,6 @@ var opcodeTable = [...]opInfo{
argLen: 3,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: x86.AORB,
reg: regInfo{
inputs: []inputInfo{
@@ -10083,7 +10073,6 @@ var opcodeTable = [...]opInfo{
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
},
@@ -10097,7 +10086,6 @@ var opcodeTable = [...]opInfo{
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
},
@@ -10111,7 +10099,6 @@ var opcodeTable = [...]opInfo{
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,7 +10112,6 @@ var opcodeTable = [...]opInfo{
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
},
@@ -10139,7 +10125,6 @@ var opcodeTable = [...]opInfo{
inputs: []inputInfo{
{0, 4294901760}, // F0 F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 F13 F14 F15
},
clobbers: 2147483648, // F15
outputs: []outputInfo{
{0, 21503}, // R0 R1 R2 R3 R4 R5 R6 R7 R8 R9 R12 R14
},
@@ -10153,7 +10138,6 @@ var opcodeTable = [...]opInfo{
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
},
@@ -10167,7 +10151,6 @@ var opcodeTable = [...]opInfo{
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
},
@@ -10181,7 +10164,6 @@ var opcodeTable = [...]opInfo{
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
},
@@ -12673,7 +12655,6 @@ var opcodeTable = [...]opInfo{
name: "STLR",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: arm64.ASTLR,
reg: regInfo{
inputs: []inputInfo{
@@ -12686,7 +12667,6 @@ var opcodeTable = [...]opInfo{
name: "STLRW",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: arm64.ASTLRW,
reg: regInfo{
inputs: []inputInfo{
@@ -12700,7 +12680,6 @@ var opcodeTable = [...]opInfo{
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
@@ -12716,7 +12695,6 @@ var opcodeTable = [...]opInfo{
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
@@ -12732,7 +12710,6 @@ var opcodeTable = [...]opInfo{
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
@@ -12748,7 +12725,6 @@ var opcodeTable = [...]opInfo{
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
@@ -12765,7 +12741,6 @@ var opcodeTable = [...]opInfo{
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
@@ -12783,7 +12758,6 @@ var opcodeTable = [...]opInfo{
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
@@ -12799,7 +12773,6 @@ var opcodeTable = [...]opInfo{
name: "LoweredAtomicAnd8",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: arm64.AAND,
reg: regInfo{
inputs: []inputInfo{
@@ -12812,7 +12785,6 @@ var opcodeTable = [...]opInfo{
name: "LoweredAtomicOr8",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: arm64.AORR,
reg: regInfo{
inputs: []inputInfo{
@@ -14003,7 +13975,6 @@ var opcodeTable = [...]opInfo{
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
@@ -14015,7 +13986,6 @@ var opcodeTable = [...]opInfo{
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
@@ -14027,7 +13997,6 @@ var opcodeTable = [...]opInfo{
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
@@ -14043,7 +14012,6 @@ var opcodeTable = [...]opInfo{
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
@@ -14060,7 +14028,6 @@ var opcodeTable = [...]opInfo{
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
@@ -14075,7 +14042,6 @@ var opcodeTable = [...]opInfo{
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
@@ -14091,7 +14057,6 @@ var opcodeTable = [...]opInfo{
name: "LoweredAtomicAnd",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: mips.AAND,
reg: regInfo{
inputs: []inputInfo{
@@ -14104,7 +14069,6 @@ var opcodeTable = [...]opInfo{
name: "LoweredAtomicOr",
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: mips.AOR,
reg: regInfo{
inputs: []inputInfo{
@@ -18606,32 +18570,6 @@ var opcodeTable = [...]opInfo{
},
},
},
{
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,
@@ -19534,7 +19472,6 @@ var opcodeTable = [...]opInfo{
argLen: 3,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: s390x.AMOVW,
reg: regInfo{
inputs: []inputInfo{
@@ -19549,7 +19486,6 @@ var opcodeTable = [...]opInfo{
argLen: 3,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: s390x.AMOVD,
reg: regInfo{
inputs: []inputInfo{
@@ -19563,7 +19499,6 @@ var opcodeTable = [...]opInfo{
auxType: auxSymOff,
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: s390x.ALAA,
reg: regInfo{
inputs: []inputInfo{
@@ -19580,7 +19515,6 @@ var opcodeTable = [...]opInfo{
auxType: auxSymOff,
argLen: 3,
faultOnNilArg0: true,
hasSideEffects: true,
asm: s390x.ALAAG,
reg: regInfo{
inputs: []inputInfo{
@@ -19608,7 +19542,6 @@ var opcodeTable = [...]opInfo{
argLen: 4,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: s390x.ACS,
reg: regInfo{
inputs: []inputInfo{
@@ -19629,7 +19562,6 @@ var opcodeTable = [...]opInfo{
argLen: 4,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: s390x.ACSG,
reg: regInfo{
inputs: []inputInfo{
@@ -19650,7 +19582,6 @@ var opcodeTable = [...]opInfo{
argLen: 3,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: s390x.ACS,
reg: regInfo{
inputs: []inputInfo{
@@ -19669,7 +19600,6 @@ var opcodeTable = [...]opInfo{
argLen: 3,
clobberFlags: true,
faultOnNilArg0: true,
hasSideEffects: true,
asm: s390x.ACSG,
reg: regInfo{
inputs: []inputInfo{
@@ -21457,70 +21387,59 @@ var opcodeTable = [...]opInfo{
generic: true,
},
{
name: "AtomicStore32",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicStore32",
argLen: 3,
generic: true,
},
{
name: "AtomicStore64",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicStore64",
argLen: 3,
generic: true,
},
{
name: "AtomicStorePtrNoWB",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicStorePtrNoWB",
argLen: 3,
generic: true,
},
{
name: "AtomicExchange32",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicExchange32",
argLen: 3,
generic: true,
},
{
name: "AtomicExchange64",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicExchange64",
argLen: 3,
generic: true,
},
{
name: "AtomicAdd32",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicAdd32",
argLen: 3,
generic: true,
},
{
name: "AtomicAdd64",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicAdd64",
argLen: 3,
generic: true,
},
{
name: "AtomicCompareAndSwap32",
argLen: 4,
hasSideEffects: true,
generic: true,
name: "AtomicCompareAndSwap32",
argLen: 4,
generic: true,
},
{
name: "AtomicCompareAndSwap64",
argLen: 4,
hasSideEffects: true,
generic: true,
name: "AtomicCompareAndSwap64",
argLen: 4,
generic: true,
},
{
name: "AtomicAnd8",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicAnd8",
argLen: 3,
generic: true,
},
{
name: "AtomicOr8",
argLen: 3,
hasSideEffects: true,
generic: true,
name: "AtomicOr8",
argLen: 3,
generic: true,
},
}

View File

@@ -1699,24 +1699,6 @@ sinking:
}
p := d.Preds[0].b // block in loop exiting to d.
// Check that the spill value is still live at the start of d.
// If it isn't, we can't move the spill here because some other value
// may be using the same stack slot. See issue 20472.
// The spill value can't be defined in d, so that makes our lives easier.
for _, x := range stacklive[d.ID] {
if x == vsp.ID {
goto stillLive
}
}
for _, v := range d.Values {
if v.Op == OpLoadReg && v.Args[0] == vsp {
goto stillLive
}
}
// Spill is not live - abort sinking this spill.
continue sinking
stillLive:
endregs := s.endRegs[p.ID]
for _, regrec := range endregs {
if regrec.v == e && regrec.r != noRegister && regrec.c == e { // TODO: regrec.c != e implies different spill possible.

View File

@@ -31,68 +31,3 @@ func TestLiveControlOps(t *testing.T) {
regalloc(f.f)
checkFunc(f.f)
}
func TestSpillMove(t *testing.T) {
// Test for issue 20472. We shouldn't move a spill out to exit blocks
// if there is an exit block where the spill is dead but the pre-spill
// value is live.
c := testConfig(t)
ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
arg1Aux := c.fe.Auto(TypeInt64)
arg2Aux := c.fe.Auto(ptrType)
f := Fun(c, "entry",
Bloc("entry",
Valu("mem", OpInitMem, TypeMem, 0, nil),
Valu("x", OpArg, TypeInt64, 0, arg1Aux),
Valu("p", OpArg, ptrType, 0, arg2Aux),
Valu("a", OpAMD64TESTQ, TypeFlags, 0, nil, "x", "x"),
Goto("loop1"),
),
Bloc("loop1",
Valu("y", OpAMD64MULQ, TypeInt64, 0, nil, "x", "x"),
Eq("a", "loop2", "exit1"),
),
Bloc("loop2",
Eq("a", "loop1", "exit2"),
),
Bloc("exit1",
// store before call, y is available in a register
Valu("mem2", OpAMD64MOVQstore, TypeMem, 0, nil, "p", "y", "mem"),
Valu("mem3", OpAMD64CALLstatic, TypeMem, 0, nil, "mem2"),
Exit("mem3"),
),
Bloc("exit2",
// store after call, y must be loaded from a spill location
Valu("mem4", OpAMD64CALLstatic, TypeMem, 0, nil, "mem"),
Valu("mem5", OpAMD64MOVQstore, TypeMem, 0, nil, "p", "y", "mem4"),
Exit("mem5"),
),
)
flagalloc(f.f)
regalloc(f.f)
checkFunc(f.f)
// There should still be a spill in Loop1, and nowhere else.
if numSpills(f.blocks["loop1"]) != 1 {
t.Errorf("spill missing from loop1")
}
if numSpills(f.blocks["loop2"]) != 0 {
t.Errorf("spill present in loop2")
}
if numSpills(f.blocks["exit1"]) != 0 {
t.Errorf("spill present in exit1")
}
if numSpills(f.blocks["exit2"]) != 0 {
t.Errorf("spill present in exit2")
}
}
func numSpills(b *Block) int {
n := 0
for _, v := range b.Values {
if v.Op == OpStoreReg {
n++
}
}
return n
}

View File

@@ -14517,7 +14517,7 @@ func rewriteValueARM_OpLrot16(v *Value, config *Config) bool {
_ = b
// match: (Lrot16 <t> x [c])
// cond:
// result: (OR (SLLconst <t> x [c&15]) (SRLconst <t> (ZeroExt16to32 x) [16-c&15]))
// result: (OR (SLLconst <t> x [c&15]) (SRLconst <t> x [16-c&15]))
for {
t := v.Type
c := v.AuxInt
@@ -14529,9 +14529,7 @@ func rewriteValueARM_OpLrot16(v *Value, config *Config) bool {
v.AddArg(v0)
v1 := b.NewValue0(v.Line, OpARMSRLconst, t)
v1.AuxInt = 16 - c&15
v2 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
v2.AddArg(x)
v1.AddArg(v2)
v1.AddArg(x)
v.AddArg(v1)
return true
}
@@ -14556,7 +14554,7 @@ func rewriteValueARM_OpLrot8(v *Value, config *Config) bool {
_ = b
// match: (Lrot8 <t> x [c])
// cond:
// result: (OR (SLLconst <t> x [c&7]) (SRLconst <t> (ZeroExt8to32 x) [8-c&7]))
// result: (OR (SLLconst <t> x [c&7]) (SRLconst <t> x [8-c&7]))
for {
t := v.Type
c := v.AuxInt
@@ -14568,9 +14566,7 @@ func rewriteValueARM_OpLrot8(v *Value, config *Config) bool {
v.AddArg(v0)
v1 := b.NewValue0(v.Line, OpARMSRLconst, t)
v1.AuxInt = 8 - c&7
v2 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
v2.AddArg(x)
v1.AddArg(v2)
v1.AddArg(x)
v.AddArg(v1)
return true
}

View File

@@ -2625,7 +2625,7 @@ func rewriteValueARM64_OpARM64FMOVDload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (FMOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (FMOVDload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -2637,7 +2637,7 @@ func rewriteValueARM64_OpARM64FMOVDload(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64FMOVDload)
@@ -2648,7 +2648,7 @@ func rewriteValueARM64_OpARM64FMOVDload(v *Value, config *Config) bool {
return true
}
// match: (FMOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (FMOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -2661,7 +2661,7 @@ func rewriteValueARM64_OpARM64FMOVDload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64FMOVDload)
@@ -2677,7 +2677,7 @@ func rewriteValueARM64_OpARM64FMOVDstore(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (FMOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (FMOVDstore [off1+off2] {sym} ptr val mem)
for {
off1 := v.AuxInt
@@ -2690,7 +2690,7 @@ func rewriteValueARM64_OpARM64FMOVDstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64FMOVDstore)
@@ -2702,7 +2702,7 @@ func rewriteValueARM64_OpARM64FMOVDstore(v *Value, config *Config) bool {
return true
}
// match: (FMOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (FMOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
for {
off1 := v.AuxInt
@@ -2716,7 +2716,7 @@ func rewriteValueARM64_OpARM64FMOVDstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64FMOVDstore)
@@ -2733,7 +2733,7 @@ func rewriteValueARM64_OpARM64FMOVSload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (FMOVSload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (FMOVSload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -2745,7 +2745,7 @@ func rewriteValueARM64_OpARM64FMOVSload(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64FMOVSload)
@@ -2756,7 +2756,7 @@ func rewriteValueARM64_OpARM64FMOVSload(v *Value, config *Config) bool {
return true
}
// match: (FMOVSload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (FMOVSload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -2769,7 +2769,7 @@ func rewriteValueARM64_OpARM64FMOVSload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64FMOVSload)
@@ -2785,7 +2785,7 @@ func rewriteValueARM64_OpARM64FMOVSstore(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (FMOVSstore [off1] {sym} (ADDconst [off2] ptr) val mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (FMOVSstore [off1+off2] {sym} ptr val mem)
for {
off1 := v.AuxInt
@@ -2798,7 +2798,7 @@ func rewriteValueARM64_OpARM64FMOVSstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64FMOVSstore)
@@ -2810,7 +2810,7 @@ func rewriteValueARM64_OpARM64FMOVSstore(v *Value, config *Config) bool {
return true
}
// match: (FMOVSstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (FMOVSstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
for {
off1 := v.AuxInt
@@ -2824,7 +2824,7 @@ func rewriteValueARM64_OpARM64FMOVSstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64FMOVSstore)
@@ -3511,7 +3511,7 @@ func rewriteValueARM64_OpARM64MOVBUload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVBUload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2)
// cond:
// result: (MOVBUload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -3523,9 +3523,6 @@ func rewriteValueARM64_OpARM64MOVBUload(v *Value, config *Config) bool {
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
@@ -3534,7 +3531,7 @@ func rewriteValueARM64_OpARM64MOVBUload(v *Value, config *Config) bool {
return true
}
// match: (MOVBUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
// cond: canMergeSym(sym1,sym2)
// result: (MOVBUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -3547,7 +3544,7 @@ func rewriteValueARM64_OpARM64MOVBUload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
if !(canMergeSym(sym1, sym2)) {
break
}
v.reset(OpARM64MOVBUload)
@@ -3626,7 +3623,7 @@ func rewriteValueARM64_OpARM64MOVBload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVBload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2)
// cond:
// result: (MOVBload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -3638,9 +3635,6 @@ func rewriteValueARM64_OpARM64MOVBload(v *Value, config *Config) bool {
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
@@ -3649,7 +3643,7 @@ func rewriteValueARM64_OpARM64MOVBload(v *Value, config *Config) bool {
return true
}
// match: (MOVBload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
// cond: canMergeSym(sym1,sym2)
// result: (MOVBload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -3662,7 +3656,7 @@ func rewriteValueARM64_OpARM64MOVBload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
if !(canMergeSym(sym1, sym2)) {
break
}
v.reset(OpARM64MOVBload)
@@ -3741,7 +3735,7 @@ func rewriteValueARM64_OpARM64MOVBstore(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVBstore [off1] {sym} (ADDconst [off2] ptr) val mem)
// cond: is32Bit(off1+off2)
// cond:
// result: (MOVBstore [off1+off2] {sym} ptr val mem)
for {
off1 := v.AuxInt
@@ -3754,9 +3748,6 @@ func rewriteValueARM64_OpARM64MOVBstore(v *Value, config *Config) bool {
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
@@ -3766,7 +3757,7 @@ func rewriteValueARM64_OpARM64MOVBstore(v *Value, config *Config) bool {
return true
}
// match: (MOVBstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
// cond: canMergeSym(sym1,sym2)
// result: (MOVBstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
for {
off1 := v.AuxInt
@@ -3780,7 +3771,7 @@ func rewriteValueARM64_OpARM64MOVBstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
if !(canMergeSym(sym1, sym2)) {
break
}
v.reset(OpARM64MOVBstore)
@@ -3945,7 +3936,7 @@ func rewriteValueARM64_OpARM64MOVBstorezero(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVBstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2)
// cond:
// result: (MOVBstorezero [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -3957,9 +3948,6 @@ func rewriteValueARM64_OpARM64MOVBstorezero(v *Value, config *Config) bool {
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
@@ -3968,7 +3956,7 @@ func rewriteValueARM64_OpARM64MOVBstorezero(v *Value, config *Config) bool {
return true
}
// match: (MOVBstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// cond: canMergeSym(sym1,sym2) && is32Bit(off1+off2)
// cond: canMergeSym(sym1,sym2)
// result: (MOVBstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -3981,7 +3969,7 @@ func rewriteValueARM64_OpARM64MOVBstorezero(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
if !(canMergeSym(sym1, sym2) && is32Bit(off1+off2)) {
if !(canMergeSym(sym1, sym2)) {
break
}
v.reset(OpARM64MOVBstorezero)
@@ -3997,7 +3985,7 @@ func rewriteValueARM64_OpARM64MOVDload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVDload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVDload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -4009,7 +3997,7 @@ func rewriteValueARM64_OpARM64MOVDload(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVDload)
@@ -4020,7 +4008,7 @@ func rewriteValueARM64_OpARM64MOVDload(v *Value, config *Config) bool {
return true
}
// match: (MOVDload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVDload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -4033,7 +4021,7 @@ func rewriteValueARM64_OpARM64MOVDload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVDload)
@@ -4100,7 +4088,7 @@ func rewriteValueARM64_OpARM64MOVDstore(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVDstore [off1] {sym} (ADDconst [off2] ptr) val mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVDstore [off1+off2] {sym} ptr val mem)
for {
off1 := v.AuxInt
@@ -4113,7 +4101,7 @@ func rewriteValueARM64_OpARM64MOVDstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVDstore)
@@ -4125,7 +4113,7 @@ func rewriteValueARM64_OpARM64MOVDstore(v *Value, config *Config) bool {
return true
}
// match: (MOVDstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVDstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
for {
off1 := v.AuxInt
@@ -4139,7 +4127,7 @@ func rewriteValueARM64_OpARM64MOVDstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVDstore)
@@ -4178,7 +4166,7 @@ func rewriteValueARM64_OpARM64MOVDstorezero(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVDstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%2==8 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVDstorezero [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -4190,7 +4178,7 @@ func rewriteValueARM64_OpARM64MOVDstorezero(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 8 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%2 == 8 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVDstorezero)
@@ -4201,7 +4189,7 @@ func rewriteValueARM64_OpARM64MOVDstorezero(v *Value, config *Config) bool {
return true
}
// match: (MOVDstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%8==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVDstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -4214,7 +4202,7 @@ func rewriteValueARM64_OpARM64MOVDstorezero(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%8 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVDstorezero)
@@ -4230,7 +4218,7 @@ func rewriteValueARM64_OpARM64MOVHUload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVHUload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVHUload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -4242,7 +4230,7 @@ func rewriteValueARM64_OpARM64MOVHUload(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVHUload)
@@ -4253,7 +4241,7 @@ func rewriteValueARM64_OpARM64MOVHUload(v *Value, config *Config) bool {
return true
}
// match: (MOVHUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVHUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -4266,7 +4254,7 @@ func rewriteValueARM64_OpARM64MOVHUload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVHUload)
@@ -4369,7 +4357,7 @@ func rewriteValueARM64_OpARM64MOVHload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVHload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVHload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -4381,7 +4369,7 @@ func rewriteValueARM64_OpARM64MOVHload(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVHload)
@@ -4392,7 +4380,7 @@ func rewriteValueARM64_OpARM64MOVHload(v *Value, config *Config) bool {
return true
}
// match: (MOVHload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVHload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -4405,7 +4393,7 @@ func rewriteValueARM64_OpARM64MOVHload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVHload)
@@ -4532,7 +4520,7 @@ func rewriteValueARM64_OpARM64MOVHstore(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVHstore [off1] {sym} (ADDconst [off2] ptr) val mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVHstore [off1+off2] {sym} ptr val mem)
for {
off1 := v.AuxInt
@@ -4545,7 +4533,7 @@ func rewriteValueARM64_OpARM64MOVHstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVHstore)
@@ -4557,7 +4545,7 @@ func rewriteValueARM64_OpARM64MOVHstore(v *Value, config *Config) bool {
return true
}
// match: (MOVHstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVHstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
for {
off1 := v.AuxInt
@@ -4571,7 +4559,7 @@ func rewriteValueARM64_OpARM64MOVHstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVHstore)
@@ -4694,7 +4682,7 @@ func rewriteValueARM64_OpARM64MOVHstorezero(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVHstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVHstorezero [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -4706,7 +4694,7 @@ func rewriteValueARM64_OpARM64MOVHstorezero(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVHstorezero)
@@ -4717,7 +4705,7 @@ func rewriteValueARM64_OpARM64MOVHstorezero(v *Value, config *Config) bool {
return true
}
// match: (MOVHstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%2==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVHstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -4730,7 +4718,7 @@ func rewriteValueARM64_OpARM64MOVHstorezero(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%2 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVHstorezero)
@@ -4746,7 +4734,7 @@ func rewriteValueARM64_OpARM64MOVWUload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVWUload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVWUload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -4758,7 +4746,7 @@ func rewriteValueARM64_OpARM64MOVWUload(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVWUload)
@@ -4769,7 +4757,7 @@ func rewriteValueARM64_OpARM64MOVWUload(v *Value, config *Config) bool {
return true
}
// match: (MOVWUload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVWUload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -4782,7 +4770,7 @@ func rewriteValueARM64_OpARM64MOVWUload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVWUload)
@@ -4909,7 +4897,7 @@ func rewriteValueARM64_OpARM64MOVWload(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVWload [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVWload [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -4921,7 +4909,7 @@ func rewriteValueARM64_OpARM64MOVWload(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVWload)
@@ -4932,7 +4920,7 @@ func rewriteValueARM64_OpARM64MOVWload(v *Value, config *Config) bool {
return true
}
// match: (MOVWload [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVWload [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -4945,7 +4933,7 @@ func rewriteValueARM64_OpARM64MOVWload(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVWload)
@@ -5120,7 +5108,7 @@ func rewriteValueARM64_OpARM64MOVWstore(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVWstore [off1] {sym} (ADDconst [off2] ptr) val mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVWstore [off1+off2] {sym} ptr val mem)
for {
off1 := v.AuxInt
@@ -5133,7 +5121,7 @@ func rewriteValueARM64_OpARM64MOVWstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVWstore)
@@ -5145,7 +5133,7 @@ func rewriteValueARM64_OpARM64MOVWstore(v *Value, config *Config) bool {
return true
}
// match: (MOVWstore [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) val mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVWstore [off1+off2] {mergeSym(sym1,sym2)} ptr val mem)
for {
off1 := v.AuxInt
@@ -5159,7 +5147,7 @@ func rewriteValueARM64_OpARM64MOVWstore(v *Value, config *Config) bool {
ptr := v_0.Args[0]
val := v.Args[1]
mem := v.Args[2]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVWstore)
@@ -5240,7 +5228,7 @@ func rewriteValueARM64_OpARM64MOVWstorezero(v *Value, config *Config) bool {
b := v.Block
_ = b
// match: (MOVWstorezero [off1] {sym} (ADDconst [off2] ptr) mem)
// cond: is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isAuto(sym))
// cond: (off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym) && !isAuto(sym)
// result: (MOVWstorezero [off1+off2] {sym} ptr mem)
for {
off1 := v.AuxInt
@@ -5252,7 +5240,7 @@ func rewriteValueARM64_OpARM64MOVWstorezero(v *Value, config *Config) bool {
off2 := v_0.AuxInt
ptr := v_0.Args[0]
mem := v.Args[1]
if !(is32Bit(off1+off2) && !isArg(sym) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isAuto(sym))) {
if !((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym) && !isAuto(sym)) {
break
}
v.reset(OpARM64MOVWstorezero)
@@ -5263,7 +5251,7 @@ func rewriteValueARM64_OpARM64MOVWstorezero(v *Value, config *Config) bool {
return true
}
// match: (MOVWstorezero [off1] {sym1} (MOVDaddr [off2] {sym2} ptr) mem)
// 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)))
// cond: canMergeSym(sym1,sym2) && ((off1+off2)%4==0 || off1+off2<256 && off1+off2>-256 && !isArg(sym1) && !isAuto(sym1))
// result: (MOVWstorezero [off1+off2] {mergeSym(sym1,sym2)} ptr mem)
for {
off1 := v.AuxInt
@@ -5276,7 +5264,7 @@ func rewriteValueARM64_OpARM64MOVWstorezero(v *Value, config *Config) bool {
sym2 := v_0.Aux
ptr := v_0.Args[0]
mem := v.Args[1]
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)))) {
if !(canMergeSym(sym1, sym2) && ((off1+off2)%4 == 0 || off1+off2 < 256 && off1+off2 > -256 && !isArg(sym1) && !isAuto(sym1))) {
break
}
v.reset(OpARM64MOVWstorezero)

View File

@@ -712,7 +712,7 @@ func rewriteValueMIPS_OpAtomicAnd8(v *Value, config *Config) bool {
_ = 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] 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] (XORconst <config.fe.TypeUInt32()> [3] ptr)))))) mem)
for {
ptr := v.Args[0]
val := v.Args[1]
@@ -750,7 +750,10 @@ func rewriteValueMIPS_OpAtomicAnd8(v *Value, config *Config) bool {
v10.AuxInt = 3
v11 := b.NewValue0(v.Line, OpMIPSANDconst, config.fe.TypeUInt32())
v11.AuxInt = 3
v11.AddArg(ptr)
v12 := b.NewValue0(v.Line, OpMIPSXORconst, config.fe.TypeUInt32())
v12.AuxInt = 3
v12.AddArg(ptr)
v11.AddArg(v12)
v10.AddArg(v11)
v8.AddArg(v10)
v7.AddArg(v8)

View File

@@ -1543,12 +1543,12 @@ func rewriteValuePPC64_OpGeq16U(v *Value, config *Config) bool {
_ = b
// match: (Geq16U x y)
// cond:
// result: (GreaterEqual (CMPWU (ZeroExt16to32 x) (ZeroExt16to32 y)))
// result: (GreaterEqual (CMPU (ZeroExt16to32 x) (ZeroExt16to32 y)))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpPPC64GreaterEqual)
v0 := b.NewValue0(v.Line, OpPPC64CMPWU, TypeFlags)
v0 := b.NewValue0(v.Line, OpPPC64CMPU, TypeFlags)
v1 := b.NewValue0(v.Line, OpZeroExt16to32, config.fe.TypeUInt32())
v1.AddArg(x)
v0.AddArg(v1)
@@ -1598,12 +1598,12 @@ func rewriteValuePPC64_OpGeq32U(v *Value, config *Config) bool {
_ = b
// match: (Geq32U x y)
// cond:
// result: (GreaterEqual (CMPWU x y))
// result: (GreaterEqual (CMPU x y))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpPPC64GreaterEqual)
v0 := b.NewValue0(v.Line, OpPPC64CMPWU, TypeFlags)
v0 := b.NewValue0(v.Line, OpPPC64CMPU, TypeFlags)
v0.AddArg(x)
v0.AddArg(y)
v.AddArg(v0)
@@ -1687,12 +1687,12 @@ func rewriteValuePPC64_OpGeq8U(v *Value, config *Config) bool {
_ = b
// match: (Geq8U x y)
// cond:
// result: (GreaterEqual (CMPWU (ZeroExt8to32 x) (ZeroExt8to32 y)))
// result: (GreaterEqual (CMPU (ZeroExt8to32 x) (ZeroExt8to32 y)))
for {
x := v.Args[0]
y := v.Args[1]
v.reset(OpPPC64GreaterEqual)
v0 := b.NewValue0(v.Line, OpPPC64CMPWU, TypeFlags)
v0 := b.NewValue0(v.Line, OpPPC64CMPU, TypeFlags)
v1 := b.NewValue0(v.Line, OpZeroExt8to32, config.fe.TypeUInt32())
v1.AddArg(x)
v0.AddArg(v1)

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,6 @@ const (
ScoreMemory
ScoreDefault
ScoreFlags
ScoreSelectCall
ScoreControl // towards bottom of block
)
@@ -111,25 +110,10 @@ func schedule(f *Func) {
// We want all the vardefs next.
score[v.ID] = ScoreVarDef
case v.Type.IsMemory():
// 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
}
// 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
@@ -148,20 +132,19 @@ func schedule(f *Func) {
}
}
// TODO: make this logic permanent in types.IsMemory?
isMem := func(v *Value) bool {
return v.Type.IsMemory() || v.Type.IsTuple() && v.Type.FieldType(1).IsMemory()
}
for _, b := range f.Blocks {
// Find store chain for block.
// Store chains for different blocks overwrite each other, so
// the calculated store chain is good only for this block.
for _, v := range b.Values {
if v.Op != OpPhi && isMem(v) {
if v.Op != OpPhi && v.Type.IsMemory() {
mem := v
if v.Op == OpSelect1 {
v = v.Args[0]
}
for _, w := range v.Args {
if isMem(w) {
nextMem[w.ID] = v
if w.Type.IsMemory() {
nextMem[w.ID] = mem
}
}
}
@@ -180,15 +163,15 @@ func schedule(f *Func) {
uses[w.ID]++
}
// Any load must come before the following store.
if !isMem(v) && isMem(w) {
// v is a load.
s := nextMem[w.ID]
if s == nil || s.Block != b {
continue
}
additionalArgs[s.ID] = append(additionalArgs[s.ID], v)
uses[v.ID]++
if v.Type.IsMemory() || !w.Type.IsMemory() {
continue // not a load
}
s := nextMem[w.ID]
if s == nil || s.Block != b {
continue
}
additionalArgs[s.ID] = append(additionalArgs[s.ID], v)
uses[v.ID]++
}
}

View File

@@ -35,7 +35,7 @@ func writebarrier(f *Func) {
valueLoop:
for i, v := range b.Values {
switch v.Op {
case OpStoreWB, OpMoveWB, OpMoveWBVolatile, OpZeroWB:
case OpStoreWB, OpMoveWB, OpMoveWBVolatile:
if IsStackAddr(v.Args[0]) {
switch v.Op {
case OpStoreWB:

View File

@@ -1634,8 +1634,6 @@ func (p *parser) stmtBody(context string) []Stmt {
return body
}
var dummyCond = &Name{Value: "false"}
func (p *parser) header(forStmt bool) (init SimpleStmt, cond Expr, post SimpleStmt) {
if p.tok == _Lbrace {
return
@@ -1682,8 +1680,7 @@ func (p *parser) header(forStmt bool) (init SimpleStmt, cond Expr, post SimpleSt
case *ExprStmt:
cond = s.X
default:
p.syntax_error(fmt.Sprintf("%s used as value", String(s)))
cond = dummyCond // avoid follow-up error for if statements
p.error("invalid condition, tag, or type switch guard")
}
p.xnest = outer

View File

@@ -31,5 +31,4 @@ func Init() {
gc.Thearch.SSAMarkMoves = ssaMarkMoves
gc.Thearch.SSAGenValue = ssaGenValue
gc.Thearch.SSAGenBlock = ssaGenBlock
gc.Thearch.ZeroAuto = zeroAuto
}

View File

@@ -84,23 +84,6 @@ func zerorange(p *obj.Prog, frame int64, lo int64, hi int64, ax *uint32) *obj.Pr
return p
}
func zeroAuto(n *gc.Node, pp *obj.Prog) {
// Note: this code must not clobber any registers.
sym := gc.Linksym(n.Sym)
size := n.Type.Size()
for i := int64(0); i < size; i += 4 {
p := gc.AddAsmAfter(x86.AMOVL, pp)
pp = p
p.From.Type = obj.TYPE_CONST
p.From.Offset = 0
p.To.Type = obj.TYPE_MEM
p.To.Name = obj.NAME_AUTO
p.To.Reg = x86.REG_SP
p.To.Offset = n.Xoffset + i
p.To.Sym = sym
}
}
func ginsnop() {
p := gc.Prog(x86.AXCHGL)
p.From.Type = obj.TYPE_REG

View File

@@ -15,6 +15,7 @@ import (
"os/exec"
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
"sync"
@@ -353,7 +354,7 @@ func (t *tester) registerTests() {
// This test needs its stdout/stderr to be terminals, so we don't run it from cmd/go's tests.
// See issue 18153.
if t.goos == "linux" {
if runtime.GOOS == "linux" {
t.tests = append(t.tests, distTest{
name: "cmd_go_test_terminal",
heading: "cmd/go terminal test",
@@ -567,7 +568,7 @@ func (t *tester) registerTests() {
if t.gohostos == "linux" && t.goarch == "amd64" {
t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", "main.go")
}
if t.goos == "linux" && t.goarch == "amd64" {
if t.gohostos == "linux" && t.goarch == "amd64" {
t.registerTest("testsanitizers", "../misc/cgo/testsanitizers", "./test.bash")
}
if t.hasBash() && t.goos != "android" && !t.iOS() && t.gohostos != "windows" {

Some files were not shown because too many files have changed in this diff Show More