mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-06-10 15:29:52 +00:00
This commit was manufactured by cvs2svn to create tag 'RELEASE_1'.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_1@9499 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
e8a63eb78f
commit
c5cf3309a2
34
LICENSE.TXT
34
LICENSE.TXT
|
@ -1,37 +1,3 @@
|
|||
NOTICE:
|
||||
=======
|
||||
All distributions of LLVM prior to the 1.0 Release will be licensed to you
|
||||
under the LLVM pre-release license. The 1.0 Release will be announced on the
|
||||
LLVM Announcements Mailing List.
|
||||
|
||||
After the 1.0 Release of LLVM, the LLVM code will be licensed to you under the
|
||||
LLVM Release License (aka the Illinois Open Source License).
|
||||
|
||||
The main point is that you cannot re-distribute LLVM until the 1.0 Release.
|
||||
|
||||
==============================================================================
|
||||
LLVM pre-release license
|
||||
==============================================================================
|
||||
|
||||
This is a pre-release distribution of the LLVM software and is provided for
|
||||
evaluation only. This version of the LLVM software or modifications thereof
|
||||
should not be distributed to third parties for any purpose. Any third parties
|
||||
interested in it can request a copy directly by sending e-mail to
|
||||
llvmdev@cs.uiuc.edu. As this is an evaluation release, we would appreciate any
|
||||
and all feedback, ideas, and reports of bugs that you encounter. You may
|
||||
discuss development of LLVM on llvmdev@cs.uiuc.edu, and bugs can be submitted
|
||||
through the LLVM Bug Tracker at http://llvm.cs.uiuc.edu/bugzilla/ . We thank
|
||||
you for your interest in LLVM and look forward to any comments or feedback you
|
||||
may have.
|
||||
|
||||
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
|
||||
SOFTWARE.
|
||||
|
||||
==============================================================================
|
||||
LLVM Release License
|
||||
==============================================================================
|
||||
|
|
165
README.txt
165
README.txt
|
@ -1,106 +1,129 @@
|
|||
The LLVM Compiler Infrastructure
|
||||
http://llvm.cs.uiuc.edu
|
||||
|
||||
Welcome to LLVM!
|
||||
-----------------
|
||||
This file is intended to do four things:
|
||||
(1) help you get started using LLVM;
|
||||
(2) tell you how to get questions about LLVM answered;
|
||||
(3) tell you where to find documentation for different kinds of questions; and
|
||||
(4) tell you about three LLVM-related mailing lists.
|
||||
|
||||
This file provides the location of all important LLVM documentation. In
|
||||
particular, you should read the license information and the installation
|
||||
directions before you begin using LLVM.
|
||||
|
||||
After that, there are several technical references that will help you use LLVM.
|
||||
Consult them as necessary.
|
||||
Getting Started with LLVM
|
||||
-------------------------
|
||||
|
||||
Finally, you can find information on how to communicate with the LLVM
|
||||
developers and LLVM community. This is of primary interest if you wish to
|
||||
submit a bug, supply a patch, or just keep current with what's going on with
|
||||
LLVM.
|
||||
(1) For license information:
|
||||
llvm/LICENSE.txt
|
||||
|
||||
Introductory Literature:
|
||||
(2) Installing and compiling LLVM:
|
||||
llvm/docs/GettingStarted.html
|
||||
|
||||
LLVM Home Page:
|
||||
http://llvm.cs.uiuc.edu
|
||||
(3) Learn about features and limitations of this release:
|
||||
llvm/docs/ReleaseNotes.html
|
||||
|
||||
License Information:
|
||||
llvm/LICENSE.txt
|
||||
(4) Learn how to write a pass within the LLVM system:
|
||||
llvm/docs/WritingAnLLVMPass.html
|
||||
|
||||
Release Notes:
|
||||
llvm/docs/ReleaseNotes.html
|
||||
(5) Learn how to start a new development project using LLVM, where your
|
||||
new source code can live anywhere (outside or inside the LLVM tree),
|
||||
while using LLVM header files and libraries:
|
||||
llvm/docs/Projects.html
|
||||
|
||||
LLVM Design:
|
||||
|
||||
The LLVM Instruction Set and Compilation Strategy:
|
||||
http://llvm.cs.uiuc.edu/pubs/2002-08-09-LLVMCompilationStrategy.html
|
||||
Getting Help with LLVM
|
||||
----------------------
|
||||
|
||||
(1) If you have questions or development problems not answered in the
|
||||
documentation, send e-mail to llvmdev@cs.uiuc.edu. This mailing list is
|
||||
monitored by all the people in the LLVM group at Illinois, and you should
|
||||
expect prompt first responses.
|
||||
|
||||
(2) To report a bug, submit a bug report as described in the document:
|
||||
http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html
|
||||
|
||||
(3) We now use Bugzilla to track bugs, so you can check the status of
|
||||
previous bugs at:
|
||||
http://llvm.cs.uiuc.edu/bugs/query.cgi
|
||||
|
||||
|
||||
LLVM Documentation
|
||||
------------------
|
||||
|
||||
All the documents mentioned below except the design overview tech report
|
||||
are included as part of the LLVM release (in llvm/docs/*):
|
||||
|
||||
LLVM Design Overview:
|
||||
LLVM : A Compilation Framework for Lifelong Program Analysis
|
||||
and Transformation:
|
||||
http://llvm.cs.uiuc.edu/pubs/2003-09-30-LifelongOptimizationTR.html
|
||||
|
||||
LLVM User Guides:
|
||||
|
||||
Download and Installation Instructions:
|
||||
llvm/docs/GettingStarted.html
|
||||
Download and Installation Instructions:
|
||||
llvm/docs/GettingStarted.html
|
||||
|
||||
LLVM Command Guide:
|
||||
llvm/docs/CommandGuide/CommandGuide.html
|
||||
LLVM Command Guide:
|
||||
llvm/docs/CommandGuide/index.html
|
||||
|
||||
LLVM Assembly Language:
|
||||
llvm/docs/LangRef.html
|
||||
LLVM Assembly Language:
|
||||
llvm/docs/LangRef.html
|
||||
|
||||
LLVM Test Suite Guide:
|
||||
llvm/docs/TestingGuide.html
|
||||
LLVM Test Suite Guide:
|
||||
llvm/docs/TestingGuide.html
|
||||
|
||||
LLVM Programming Documentation:
|
||||
|
||||
LLVM Programmers Manual:
|
||||
llvm/docs/ProgrammersManual.html
|
||||
LLVM Programmers Manual:
|
||||
llvm/docs/ProgrammersManual.html
|
||||
|
||||
Writing an LLVM Pass:
|
||||
llvm/docs/WritingAnLLVMPass.html
|
||||
Writing an LLVM Pass:
|
||||
llvm/docs/WritingAnLLVMPass.html
|
||||
|
||||
Alias Analysis in LLVM:
|
||||
llvm/docs/AliasAnalysis.html
|
||||
Alias Analysis in LLVM:
|
||||
llvm/docs/AliasAnalysis.html
|
||||
|
||||
Command Line Library:
|
||||
llvm/docs/CommandLine.html
|
||||
Command Line Library:
|
||||
llvm/docs/CommandLine.html
|
||||
|
||||
Coding Standards:
|
||||
llvm/docs/CodingStandards.html
|
||||
Coding Standards:
|
||||
llvm/docs/CodingStandards.html
|
||||
|
||||
LLVM Community:
|
||||
Other LLVM Resources:
|
||||
|
||||
Submitting a Bug:
|
||||
http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html
|
||||
Submitting a Bug:
|
||||
http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html
|
||||
|
||||
Open Projects:
|
||||
llvm/docs/OpenProjects.html
|
||||
Open Projects:
|
||||
llvm/docs/OpenProjects.html
|
||||
|
||||
Creating a new LLVM Project:
|
||||
llvm/docs/Projects.html
|
||||
Creating a new LLVM Project:
|
||||
llvm/docs/Projects.html
|
||||
|
||||
Mailing Lists:
|
||||
There are several mailing lists providing LLVM users with
|
||||
information:
|
||||
Mailing Lists
|
||||
--------------
|
||||
There are three mailing lists for providing LLVM users with information:
|
||||
|
||||
o LLVM Announcements List:
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvm-announce
|
||||
(1) LLVM Announcements List:
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvm-announce
|
||||
|
||||
This is a low volume list that provides
|
||||
important announcements regarding LLVM. It is
|
||||
primarily intended to announce new releases,
|
||||
major updates to the software, etc. This list
|
||||
is highly recommended for anyone that uses LLVM.
|
||||
This is a low volume list that provides important announcements regarding
|
||||
LLVM. It is primarily intended to announce new releases, major updates to
|
||||
the software, etc. This list is highly recommended for anyone that uses
|
||||
LLVM.
|
||||
|
||||
(2) LLVM Developers List:
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev
|
||||
|
||||
o LLVM Developers List:
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev
|
||||
This list is for people who want to be included in technical discussions
|
||||
of LLVM. People post to this list when they have questions about writing
|
||||
code for or using the LLVM tools. It is relatively low volume.
|
||||
|
||||
This list is for people who want to be included
|
||||
in technical discussions of LLVM. People post
|
||||
to this list when they have questions about
|
||||
writing code for or using the LLVM tools. It
|
||||
is low volume.
|
||||
(3) LLVM Commits List
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvm-commits
|
||||
|
||||
o LLVM Commits List
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvm-commits
|
||||
|
||||
This list contains all commit messages that are
|
||||
made when LLVM developers commit code changes
|
||||
to the CVS archive. It is useful for those who
|
||||
want to stay on the bleeding edge of LLVM
|
||||
development.
|
||||
|
||||
This list is very high volume.
|
||||
This list contains all commit messages that are made when LLVM developers
|
||||
commit code changes to the CVS archive. It is useful for those who want to
|
||||
stay on the bleeding edge of LLVM development. This list is very high
|
||||
volume.
|
||||
|
||||
|
|
|
@ -494,10 +494,12 @@ printed.
|
|||
|
||||
<!-- *********************************************************************** -->
|
||||
|
||||
<hr><font size="-1">
|
||||
<hr>
|
||||
<font size="-1">
|
||||
<address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
Last modified: $Date$
|
||||
</font>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
C/C++ front-end, based on GCC 3.4, from source.</p>
|
||||
|
||||
<p><b>NOTE:</b> This is currently a somewhat fragile, error-prone
|
||||
process, and you should only try to do it if (A) you really, really,
|
||||
really can't use the binaries we distribute, and (B) you are a wicked
|
||||
good GCC hacker.</p>
|
||||
process, and you should only try to do it if
|
||||
<ul>
|
||||
<li>(A) you really, really, really can't use the binaries we distribute
|
||||
<li>(B) you need GCC to fix some of the header files on your system
|
||||
<li>(C) you are an elite GCC hacker.</p>
|
||||
</ul>
|
||||
|
||||
<p>We welcome patches to help make this process simpler.</p>
|
||||
|
||||
|
@ -105,6 +108,11 @@ good GCC hacker.</p>
|
|||
<li>No inline assembly for position independent code. At the LLVM level,
|
||||
everything is position independent.</li>
|
||||
<li>We handle <tt>.init</tt> and <tt>.fini</tt> differently.</li>
|
||||
<li>You may have to disable multilib support in your target. Using multilib
|
||||
support causes the GCC compiler driver to add a lot of "<tt>-L</tt>"
|
||||
options to the link line, which do not relate to LLVM and confuse
|
||||
<tt>gccld</tt>. To disable multilibs, delete any
|
||||
<tt>MULTILIB_OPTIONS</tt> lines from your target files.</li>
|
||||
<li>Did we mention that we don't support inline assembly? You'll probably
|
||||
have to add some fixinclude hacks to disable it in the system
|
||||
headers.</li>
|
||||
|
@ -149,6 +157,8 @@ following means:</p>
|
|||
|
||||
<hr><font size="-1">
|
||||
<address><a href="mailto:gaeke -at- uiuc.edu">Brian Gaeke</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
Last modified: $Date$
|
||||
</font>
|
||||
|
||||
|
|
15
docs/ChrisNotes.txt
Normal file
15
docs/ChrisNotes.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
* Rewrite the llvm parser/lexer in http://www.antlr.org when time permits.
|
||||
They actually do C++. Imagine that.
|
||||
* Need a way to attach bytecode block info at various levels of asm code.
|
||||
* Recognize and save comments in assembly and bytecode format
|
||||
* Encode line number table in bytecode (like #line), optional table
|
||||
|
||||
* Encode negative relative offsets in the bytecode file
|
||||
|
||||
* Apparently bison has a %pure_parser option. Maybe useful for AsmParser
|
||||
|
||||
* Implement the following derived types:
|
||||
* "packed format", like this: [4 x sbyte]: Packed SIMD datatype
|
||||
* Bytecode reader should use extensions that may or may not be linked into the
|
||||
application to read blocks. Thus an easy way to ignore symbol table info
|
||||
would be to not link in that reader into the app.
|
|
@ -831,6 +831,8 @@ something. :)
|
|||
<hr>
|
||||
<font size=-1>
|
||||
<address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
<!-- Created: Tue Jan 23 15:19:28 CST 2001 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Sun Oct 12 22:12:43 CDT 2003
|
||||
|
|
|
@ -1530,6 +1530,8 @@ line options </b></font></td></tr></table><ul>
|
|||
<hr>
|
||||
<font size=-1>
|
||||
<address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
<!-- Created: Tue Jan 23 15:19:28 CST 2001 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Fri Aug 1 16:30:11 CDT 2003
|
||||
|
|
|
@ -875,6 +875,8 @@ burg.llvm.lib analyze: ../../../include/llvm/Analysis/DSNode.h:7
|
|||
|
||||
<hr>
|
||||
<address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
<!-- Created: Wed Nov 6 19:57:57 CST 2002 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Thu Nov 14 20:00:50 CST 2002
|
||||
|
|
|
@ -138,8 +138,25 @@ LLVM: Frequently Asked Questions
|
|||
cases, this takes care of the problem. To do this, just type <tt>make
|
||||
clean</tt> and then <tt>make</tt> in the directory that fails to build.
|
||||
<p>
|
||||
|
||||
<dt><b>I've built LLVM and am testing it, but the tests freeze.</b>
|
||||
<dd>
|
||||
This is most likely occurring because you built a profile or release
|
||||
(optimized) build of LLVM and have not specified the same information on
|
||||
the <tt>gmake</tt> command line.
|
||||
<p>
|
||||
For example, if you built LLVM with the command:
|
||||
<p>
|
||||
<tt>gmake ENABLE_PROFILING=1</tt>
|
||||
<p>
|
||||
...then you must run the tests with the following commands:
|
||||
<p>
|
||||
<tt>cd llvm/test<br>gmake ENABLE_PROFILING=1</tt>
|
||||
</dl>
|
||||
<hr>
|
||||
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -90,6 +90,11 @@
|
|||
<li><tt>cd <i>where-you-want-the-C-front-end-to-live</i></tt>
|
||||
<li><tt>gunzip --stdout cfrontend.<i>platform</i>.tar.gz | tar -xvf
|
||||
-</tt>
|
||||
<li><b>Sparc Only:</b><br>
|
||||
<tt>
|
||||
cd cfrontend/sparc<br>
|
||||
./fixheaders
|
||||
</tt>
|
||||
</ol>
|
||||
|
||||
<p>
|
||||
|
@ -204,8 +209,7 @@
|
|||
native code may not work on your platform.
|
||||
<p>
|
||||
The GCC front end is not very portable at the moment. If you want to get
|
||||
it to work on another platform, you can always request
|
||||
<a href="mailto:llvm-request@zion.cs.uiuc.edu">a copy of the source</a>
|
||||
it to work on another platform, you can download a copy of the source
|
||||
and try to compile it on your platform.
|
||||
</p>
|
||||
|
||||
|
@ -377,7 +381,8 @@
|
|||
|
||||
<p>
|
||||
Before configuring and compiling the LLVM suite, you need to extract the
|
||||
LLVM GCC front end from the binary distribution. It is used for building the
|
||||
LLVM GCC front end from the binary distribution. It is used for building
|
||||
the
|
||||
bytecode libraries later used by the GCC front end for linking programs, and
|
||||
its location must be specified when the LLVM suite is configured.
|
||||
</p>
|
||||
|
@ -390,6 +395,29 @@
|
|||
-</tt>
|
||||
</ol>
|
||||
|
||||
If you are on a Sparc/Solaris machine, you will need to fix the header
|
||||
files:
|
||||
|
||||
<p>
|
||||
|
||||
<tt>
|
||||
cd cfrontend/sparc
|
||||
<br>
|
||||
./fixheaders
|
||||
</tt>
|
||||
|
||||
<p>
|
||||
The binary versions of the GCC front end may not suit all of your needs.
|
||||
For example, the binary distribution may include an old version of a system
|
||||
header file, not "fix" a header file that needs to be fixed for GCC, or it
|
||||
may be linked with libraries not available on your system.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In cases like these, you may want to try
|
||||
<a href="CFEBuildInstrs.html">building the GCC front end from source.</a>
|
||||
This is not for the faint of heart, so be forewarned.
|
||||
</p>
|
||||
<!------------------------------------------------------------------------->
|
||||
<h3><a name="config">Local LLVM Configuration</a></h3>
|
||||
<!------------------------------------------------------------------------->
|
||||
|
@ -1010,10 +1038,12 @@
|
|||
If you have any questions or run into any snags (or you have any
|
||||
additions...), please send an email to
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a>.</p>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
|
||||
<!-- Created: Mon Jul 1 02:29:02 CDT 2002 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Mon Aug 11 13:52:22 CDT 2003
|
||||
<!-- hhmts end -->
|
||||
<!-- Created: Mon Jul 1 02:29:02 CDT 2002 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Mon Aug 11 13:52:22 CDT 2003
|
||||
<!-- hhmts end -->
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -273,6 +273,8 @@ following:
|
|||
|
||||
<hr><font size-1>
|
||||
<address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
<!-- Created: Tue Aug 6 15:00:33 CDT 2002 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue Oct 14 15:57:47 CDT 2003
|
||||
|
|
|
@ -1947,6 +1947,8 @@ arbitrarily complex and require memory allocation, for example.<p>
|
|||
<hr>
|
||||
<font size=-1>
|
||||
<address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
<!-- Created: Tue Jan 23 15:19:28 CST 2001 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue Oct 21 10:43:36 CDT 2003
|
||||
|
|
|
@ -275,6 +275,8 @@ Ideas for profile guided transformations:<p>
|
|||
|
||||
<hr><font size-1>
|
||||
<address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
<!-- Created: Tue Aug 6 15:00:33 CDT 2002 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Wed Oct 1 16:48:54 CDT 2003
|
||||
|
|
|
@ -1787,6 +1787,8 @@ pointer to the parent Function.
|
|||
<hr><font size-1>
|
||||
<address>By: <a href="mailto:dhurjati@cs.uiuc.edu">Dinakar Dhurjati</a> and
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
<!-- Created: Tue Aug 6 15:00:33 CDT 2002 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Sat Sep 20 09:25:11 CDT 2003
|
||||
|
|
|
@ -383,5 +383,8 @@
|
|||
|
||||
<hr>
|
||||
Written by <a href="mailto:criswell@uiuc.edu">John Criswell</a>.
|
||||
<br>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -64,7 +64,10 @@ as well as a large suite of scalar and interprocedural optimizations.<p>
|
|||
The default optimizer sequence used by the C/C++ front-ends is:<p>
|
||||
|
||||
<ol>
|
||||
<li>CFG simplification (-simplifycfg)
|
||||
<li>Interprocedural dead code elimination (-globaldce)
|
||||
<li>Interprocedural constant propagation (-ipconstprop)
|
||||
<li>Dead argument elimination (-deadargelim)
|
||||
<li>Exception handling pruning (-prune-eh)
|
||||
<li>Function inlining (-inline)
|
||||
<li>Instruction combining (-instcombine)
|
||||
|
@ -94,6 +97,7 @@ At link-time, the following optimizations are run:<p>
|
|||
<ol>
|
||||
<li>Global constant merging (-constmerge)
|
||||
<li>[optional] Internalization [which marks most functions and global variables static] (-internalize)
|
||||
<li>Interprocedural constant propagation (-ipconstprop)
|
||||
<li>Interprocedural dead argument elimination (-deadargelim)
|
||||
<li>Instruction combining (-instcombine)
|
||||
<li>CFG simplification (-simplifycfg)
|
||||
|
@ -103,7 +107,8 @@ At link-time, the following optimizations are run:<p>
|
|||
At this time, LLVM is known to work properly with SPEC CPU 2000, the Olden
|
||||
benchmarks, and the Ptrdist benchmarks among many other programs. Note however
|
||||
that the Sparc and X86 backends do not currently support exception throwing or
|
||||
long jumping. For these programs you must use the C backend.<p>
|
||||
long jumping (including 253.perlbmk in SPEC). For these programs you must use
|
||||
the C backend.<p>
|
||||
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
|
@ -358,6 +363,10 @@ problem probably cannot be fixed.<p>
|
|||
<li><a href="http://llvm.cs.uiuc.edu/PR33">Initializers for global variables</a>
|
||||
cannot include special floating point numbers like Not-A-Number or Infinity.<p>
|
||||
|
||||
<li><a href="http://zion.cs.uiuc.edu/PR56">Zero arg vararg functions are not
|
||||
supported</a>. This should not affect LLVM produced by the C or C++
|
||||
frontends.<p>
|
||||
|
||||
<li>The code produces by the C back-end has only been tested with the Sun CC and
|
||||
GCC compilers. It is possible that it will have to be adjusted to support other
|
||||
C compilers.<p>
|
||||
|
|
|
@ -420,6 +420,8 @@
|
|||
|
||||
<hr><font size="-1">
|
||||
<address>John T. Criswell</address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
Last modified: $Date$
|
||||
</font>
|
||||
|
||||
|
|
|
@ -1274,6 +1274,8 @@ href="#Pass"><tt>Pass</tt></a>, only the other way around.<p>
|
|||
|
||||
<hr><font size-1>
|
||||
<address><a href="mailto:sabre@nondot.org">Chris Lattner</a></address>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
<!-- Created: Tue Aug 6 15:00:33 CDT 2002 -->
|
||||
<!-- hhmts start -->
|
||||
Last modified: Tue Jul 22 15:52:30 CDT 2003
|
||||
|
|
265
docs/index.html
Normal file
265
docs/index.html
Normal file
|
@ -0,0 +1,265 @@
|
|||
<html>
|
||||
<title>
|
||||
The LLVM Compiler Infrastructure
|
||||
</title>
|
||||
|
||||
<body>
|
||||
|
||||
<center>
|
||||
<h1>
|
||||
The LLVM Compiler Infrastructure
|
||||
<br>
|
||||
<a href="http://llvm.cs.uiuc.edu">http://llvm.cs.uiuc.edu</a>
|
||||
</h1>
|
||||
</center>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
Welcome to LLVM!
|
||||
</h2>
|
||||
This file is intended to do four things:
|
||||
<ol>
|
||||
<li>
|
||||
help you get started using LLVM;
|
||||
</li>
|
||||
|
||||
<li>
|
||||
tell you how to get questions about LLVM answered;
|
||||
</li>
|
||||
|
||||
<li>
|
||||
tell you where to find documentation for different kinds of questions; and
|
||||
</li>
|
||||
|
||||
<li>
|
||||
tell you about three LLVM-related mailing lists.
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
Getting Started with LLVM
|
||||
</h2>
|
||||
|
||||
<dl compact>
|
||||
<dt>
|
||||
For license information:
|
||||
<dd>
|
||||
<a href="../LICENSE.TXT">llvm/LICENSE.TXT</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Installing and compiling LLVM:
|
||||
<dd>
|
||||
<a href="GettingStarted.html">llvm/docs/GettingStarted.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Learn about features and limitations of this release:
|
||||
<dd>
|
||||
<a href="ReleaseNotes.html">llvm/docs/ReleaseNotes.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Learn how to write a pass within the LLVM system:
|
||||
<dd>
|
||||
<a href="WritingAnLLVMPass.html">llvm/docs/WritingAnLLVMPass.html </a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Learn how to start a new development project using LLVM, where your
|
||||
new source code can live anywhere (outside or inside the LLVM tree),
|
||||
while using LLVM header files and libraries:
|
||||
<dd>
|
||||
<a href="Projects.html">llvm/docs/Projects.html</a>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
Getting Help with LLVM
|
||||
</h2>
|
||||
|
||||
<ol>
|
||||
<li>
|
||||
If you have questions or development problems not answered in the
|
||||
documentation, send e-mail to llvmdev@cs.uiuc.edu. This mailing list is
|
||||
monitored by all the people in the LLVM group at Illinois, and you
|
||||
should expect prompt first responses.
|
||||
</li>
|
||||
|
||||
<li>
|
||||
To report a bug, submit a bug report as described in the document:
|
||||
<a href="http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html">
|
||||
http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html</a>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
We now use Bugzilla to track bugs, so you can check the status of
|
||||
previous bugs at:
|
||||
<a href="http://llvm.cs.uiuc.edu/bugs/query.cgi">
|
||||
http://llvm.cs.uiuc.edu/bugs/query.cgi </a>
|
||||
</li>
|
||||
</ol>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
LLVM Documentation
|
||||
</h2>
|
||||
|
||||
All the documents mentioned below except the design overview tech report
|
||||
are included as part of the LLVM release (in llvm/docs/*):
|
||||
|
||||
<h3>
|
||||
LLVM Design Overview:
|
||||
</h3>
|
||||
|
||||
<dl compact>
|
||||
<dt>
|
||||
LLVM : A Compilation Framework for Lifelong Program Analysis
|
||||
and Transformation:
|
||||
<dd>
|
||||
<a href="http://llvm.cs.uiuc.edu/pubs/2003-09-30-LifelongOptimizationTR.html">
|
||||
http://llvm.cs.uiuc.edu/pubs/2003-09-30-LifelongOptimizationTR.html </a>
|
||||
|
||||
</dl>
|
||||
|
||||
<h3>
|
||||
LLVM User Guides:
|
||||
</h3>
|
||||
|
||||
<dl compact>
|
||||
<dt>
|
||||
Download and Installation Instructions:
|
||||
<dd>
|
||||
<a href="GettingStarted.html"> llvm/docs/GettingStarted.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
LLVM Command Guide:
|
||||
<dd>
|
||||
<a href="CommandGuide/index.html">
|
||||
llvm/docs/CommandGuide/index.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
LLVM Assembly Language:
|
||||
<dd>
|
||||
<a href="LangRef.html"> llvm/docs/LangRef.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
LLVM Test Suite Guide:
|
||||
<dd>
|
||||
<a href="TestingGuide.html"> llvm/docs/TestingGuide.html</a>
|
||||
<p>
|
||||
</dl>
|
||||
|
||||
<h3>
|
||||
LLVM Programming Documentation:
|
||||
</h3>
|
||||
|
||||
<dl compact>
|
||||
<dt>
|
||||
LLVM Programmers Manual:
|
||||
<dd>
|
||||
<a href="ProgrammersManual.html"> llvm/docs/ProgrammersManual.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Writing an LLVM Pass:
|
||||
<dd>
|
||||
<a href="WritingAnLLVMPass.html"> llvm/docs/WritingAnLLVMPass.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Alias Analysis in LLVM:
|
||||
<dd>
|
||||
<a href="AliasAnalysis.html"> llvm/docs/AliasAnalysis.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Command Line Library:
|
||||
<dd>
|
||||
<a href="CommandLine.html"> llvm/docs/CommandLine.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Coding Standards:
|
||||
<dd>
|
||||
<a href="CodingStandards.html"> llvm/docs/CodingStandards.html</a>
|
||||
<p>
|
||||
</dl>
|
||||
|
||||
<h3>
|
||||
Other LLVM Resources:
|
||||
</h3>
|
||||
|
||||
<dl compact>
|
||||
<dt>
|
||||
Submitting a Bug:
|
||||
<dd>
|
||||
<a href="http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html">
|
||||
http://llvm.cs.uiuc.edu/docs/HowToSubmitABug.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Open Projects:
|
||||
<dd>
|
||||
<a href="OpenProjects.html"> llvm/docs/OpenProjects.html</a>
|
||||
<p>
|
||||
|
||||
<dt>
|
||||
Creating a new LLVM Project:
|
||||
<dd>
|
||||
<a href="Projects.html"> llvm/docs/Projects.html</a>
|
||||
<p>
|
||||
</dl>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>
|
||||
Mailing Lists
|
||||
</h2>
|
||||
There are three mailing lists for providing LLVM users with information:
|
||||
|
||||
<ol>
|
||||
<li> LLVM Announcements List:<br>
|
||||
<a href="http://mail.cs.uiuc.edu/mailman/listinfo/llvm-announce">
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvm-announce</a>
|
||||
|
||||
<p>
|
||||
This is a low volume list that provides important announcements regarding
|
||||
LLVM. It is primarily intended to announce new releases, major updates to
|
||||
the software, etc. This list is highly recommended for anyone that uses
|
||||
LLVM.
|
||||
</p>
|
||||
|
||||
<li> LLVM Developers List:<br>
|
||||
<a href="http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev">
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev</a>
|
||||
|
||||
<p>
|
||||
This list is for people who want to be included in technical discussions
|
||||
of LLVM. People post to this list when they have questions about writing
|
||||
code for or using the LLVM tools. It is relatively low volume.
|
||||
</p>
|
||||
|
||||
<li> LLVM Commits List<br>
|
||||
<a href="http://mail.cs.uiuc.edu/mailman/listinfo/llvm-commits">
|
||||
http://mail.cs.uiuc.edu/mailman/listinfo/llvm-commits</a>
|
||||
|
||||
<p>
|
||||
This list contains all commit messages that are made when LLVM developers
|
||||
commit code changes to the CVS archive. It is useful for those who want to
|
||||
stay on the bleeding edge of LLVM development. This list is very high
|
||||
volume.
|
||||
</p>
|
||||
</ol>
|
||||
</body>
|
||||
</html>
|
||||
|
23
include/Config/strings.h
Normal file
23
include/Config/strings.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file was developed by the LLVM research group and is distributed under
|
||||
* the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
*
|
||||
*===----------------------------------------------------------------------===//
|
||||
*
|
||||
* Description:
|
||||
* This header file is the autoconf replacement for strings.h (if it lives
|
||||
* on the system).
|
||||
*/
|
||||
|
||||
#ifndef _CONFIG_STRINGS_H
|
||||
#define _CONFIG_STRINGS_H
|
||||
|
||||
#include "Config/config.h"
|
||||
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -39,6 +39,10 @@ private:
|
|||
///
|
||||
void IncorporateType(const Type *Ty);
|
||||
|
||||
/// IncorporateSymbolTable - Include any named types.
|
||||
///
|
||||
void IncorporateSymbolTable(const SymbolTable &ST);
|
||||
|
||||
public:
|
||||
/// run - This incorporates all types used by the specified module
|
||||
bool run(Module &M);
|
||||
|
|
|
@ -1,240 +0,0 @@
|
|||
/* Title: SparcRegClassInfo.h -*- C++ -*-
|
||||
Author: Ruchira Sasanka
|
||||
Date: Aug 20, 01
|
||||
Purpose: Contains the description of integer register class of Sparc
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SPARC_INT_REG_CLASS_H
|
||||
#define SPARC_INT_REG_CLASS_H
|
||||
|
||||
#include "llvm/Target/RegInfo.h"
|
||||
#include "llvm/CodeGen/IGNode.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Integer Register Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Int register names in same order as enum in class SparcIntRegOrder
|
||||
|
||||
static string const IntRegNames[] =
|
||||
{ "g1", "g2", "g3", "g4", "g5", "g6", "g7",
|
||||
"o0", "o1", "o2", "o3", "o4", "o5", "o7",
|
||||
"l0", "l1", "l2", "l3", "l4", "l5", "l6", "l7",
|
||||
"i0", "i1", "i2", "i3", "i4", "i5",
|
||||
"g0", "i6", "i7", "o6" };
|
||||
|
||||
|
||||
|
||||
class SparcIntRegOrder{
|
||||
|
||||
public:
|
||||
|
||||
enum RegsInPrefOrder // colors possible for a LR (in preferred order)
|
||||
{
|
||||
// --- following colors are volatile across function calls
|
||||
// %g0 can't be used for coloring - always 0
|
||||
|
||||
g1, g2, g3, g4, g5, g6, g7, //%g1-%g7
|
||||
o0, o1, o2, o3, o4, o5, o7, // %o0-%o5,
|
||||
|
||||
// %o6 is sp,
|
||||
// all %0's can get modified by a call
|
||||
|
||||
// --- following colors are NON-volatile across function calls
|
||||
|
||||
l0, l1, l2, l3, l4, l5, l6, l7, // %l0-%l7
|
||||
i0, i1, i2, i3, i4, i5, // %i0-%i5: i's need not be preserved
|
||||
|
||||
// %i6 is the fp - so not allocated
|
||||
// %i7 is the ret address - can be used if saved
|
||||
|
||||
// max # of colors reg coloring can allocate (NumOfAvailRegs)
|
||||
|
||||
// --- following colors are not available for allocation within this phase
|
||||
// --- but can appear for pre-colored ranges
|
||||
|
||||
g0, i6, i7, o6
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
// max # of colors reg coloring can allocate
|
||||
static unsigned int const NumOfAvailRegs = g0;
|
||||
|
||||
static unsigned int const StartOfNonVolatileRegs = l0;
|
||||
static unsigned int const StartOfAllRegs = g1;
|
||||
static unsigned int const NumOfAllRegs = o6 + 1;
|
||||
|
||||
|
||||
static const string getRegName(const unsigned reg) {
|
||||
assert( reg < NumOfAllRegs );
|
||||
return IntRegNames[reg];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SparcIntRegClass : public MachineRegClassInfo
|
||||
{
|
||||
public:
|
||||
|
||||
SparcIntRegClass(unsigned ID)
|
||||
: MachineRegClassInfo(ID,
|
||||
SparcIntRegOrder::NumOfAvailRegs,
|
||||
SparcIntRegOrder::NumOfAllRegs)
|
||||
{ }
|
||||
|
||||
void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const;
|
||||
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Float Register Class
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static string const FloatRegNames[] =
|
||||
{
|
||||
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9",
|
||||
"f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19",
|
||||
"f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29",
|
||||
"f30", "f31", "f32", "f33", "f34", "f35", "f36", "f37", "f38", "f39",
|
||||
"f40", "f41", "f42", "f43", "f44", "f45", "f46", "f47", "f48", "f49",
|
||||
"f50", "f51", "f52", "f53", "f54", "f55", "f56", "f57", "f58", "f59",
|
||||
"f60", "f61", "f62", "f63"
|
||||
};
|
||||
|
||||
|
||||
class SparcFloatRegOrder{
|
||||
|
||||
public:
|
||||
|
||||
enum RegsInPrefOrder {
|
||||
|
||||
f0, f1, f2, f3, f4, f5, f6, f7, f8, f9,
|
||||
f10, f11, f12, f13, f14, f15, f16, f17, f18, f19,
|
||||
f20, f21, f22, f23, f24, f25, f26, f27, f28, f29,
|
||||
f30, f31, f32, f33, f34, f35, f36, f37, f38, f39,
|
||||
f40, f41, f42, f43, f44, f45, f46, f47, f48, f49,
|
||||
f50, f51, f52, f53, f54, f55, f56, f57, f58, f59,
|
||||
f60, f61, f62, f63
|
||||
|
||||
};
|
||||
|
||||
// there are 64 regs alltogether but only 32 regs can be allocated at
|
||||
// a time.
|
||||
|
||||
static unsigned int const NumOfAvailRegs = 32;
|
||||
static unsigned int const NumOfAllRegs = 64;
|
||||
|
||||
static unsigned int const StartOfNonVolatileRegs = f6;
|
||||
static unsigned int const StartOfAllRegs = f0;
|
||||
|
||||
|
||||
static const string getRegName(const unsigned reg) {
|
||||
assert( reg < NumOfAllRegs );
|
||||
return FloatRegNames[reg];
|
||||
}
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SparcFloatRegClass : public MachineRegClassInfo
|
||||
{
|
||||
private:
|
||||
|
||||
int findFloatColor(const IGNode *const Node, unsigned Start,
|
||||
unsigned End, bool IsColorUsedArr[] ) const;
|
||||
|
||||
public:
|
||||
|
||||
SparcFloatRegClass(unsigned ID)
|
||||
: MachineRegClassInfo(ID,
|
||||
SparcFloatRegOrder::NumOfAvailRegs,
|
||||
SparcFloatRegOrder::NumOfAllRegs)
|
||||
{ }
|
||||
|
||||
void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Int CC Register Class
|
||||
// Only one integer cc register is available
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class SparcIntCCRegClass : public MachineRegClassInfo
|
||||
{
|
||||
public:
|
||||
|
||||
SparcIntCCRegClass(unsigned ID)
|
||||
: MachineRegClassInfo(ID,1, 1) { }
|
||||
|
||||
inline void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
|
||||
Node->setColor(0); // only one int cc reg is available
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Float CC Register Class
|
||||
// Only 4 Float CC registers are available
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
static string const FloatCCRegNames[] =
|
||||
{
|
||||
"fcc0", "fcc1", "fcc2", "fcc3"
|
||||
};
|
||||
|
||||
|
||||
class SparcFloatCCRegOrder{
|
||||
|
||||
public:
|
||||
|
||||
enum RegsInPrefOrder {
|
||||
|
||||
fcc0, fcc1, fcc2, fcc3
|
||||
};
|
||||
|
||||
static const string getRegName(const unsigned reg) {
|
||||
assert( reg < 4 );
|
||||
return FloatCCRegNames[reg];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
class SparcFloatCCRegClass : public MachineRegClassInfo
|
||||
{
|
||||
public:
|
||||
|
||||
SparcFloatCCRegClass(unsigned ID)
|
||||
: MachineRegClassInfo(ID, 4, 4) { }
|
||||
|
||||
void colorIGNode(IGNode * Node, bool IsColorUsedArr[] ) const {
|
||||
int c;
|
||||
for(c=0; c < 4 && IsColorUsedArr[c] ; ++c) ; // find color
|
||||
assert( (c < 4) && "Can allocate only 4 float cc registers");
|
||||
Node->setColor(c);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -41,12 +41,22 @@ void FindUsedTypes::IncorporateType(const Type *Ty) {
|
|||
IncorporateType(*I);
|
||||
}
|
||||
|
||||
void FindUsedTypes::IncorporateSymbolTable(const SymbolTable &ST) {
|
||||
SymbolTable::const_iterator TI = ST.find(Type::TypeTy);
|
||||
if (TI == ST.end()) return; // No named types
|
||||
|
||||
for (SymbolTable::type_const_iterator I = TI->second.begin(),
|
||||
E = TI->second.end(); I != E; ++I)
|
||||
IncorporateType(cast<Type>(I->second));
|
||||
}
|
||||
|
||||
// run - This incorporates all types used by the specified module
|
||||
//
|
||||
bool FindUsedTypes::run(Module &m) {
|
||||
UsedTypes.clear(); // reset if run multiple times...
|
||||
|
||||
IncorporateSymbolTable(m.getSymbolTable());
|
||||
|
||||
// Loop over global variables, incorporating their types
|
||||
for (Module::const_giterator I = m.gbegin(), E = m.gend(); I != E; ++I)
|
||||
IncorporateType(I->getType());
|
||||
|
@ -54,6 +64,7 @@ bool FindUsedTypes::run(Module &m) {
|
|||
for (Module::iterator MI = m.begin(), ME = m.end(); MI != ME; ++MI) {
|
||||
IncorporateType(MI->getType());
|
||||
const Function &F = *MI;
|
||||
IncorporateSymbolTable(F.getSymbolTable());
|
||||
|
||||
// Loop over all of the instructions in the function, adding their return
|
||||
// type as well as the types of their operands.
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,332 +0,0 @@
|
|||
//===-- InstrForest.cpp - Build instruction forest for inst selection -----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The key goal is to group instructions into a single
|
||||
// tree if one or more of them might be potentially combined into a single
|
||||
// complex instruction in the target machine.
|
||||
// Since this grouping is completely machine-independent, we do it as
|
||||
// aggressive as possible to exploit any possible target instructions.
|
||||
// In particular, we group two instructions O and I if:
|
||||
// (1) Instruction O computes an operand used by instruction I,
|
||||
// and (2) O and I are part of the same basic block,
|
||||
// and (3) O has only a single use, viz., I.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Constant.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/iTerminators.h"
|
||||
#include "llvm/iMemory.h"
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/CodeGen/InstrForest.h"
|
||||
#include "llvm/CodeGen/MachineCodeForInstruction.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "Support/STLExtras.h"
|
||||
#include "Config/alloca.h"
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// class InstrTreeNode
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
InstrTreeNode::dump(int dumpChildren, int indent) const {
|
||||
dumpNode(indent);
|
||||
|
||||
if (dumpChildren) {
|
||||
if (LeftChild)
|
||||
LeftChild->dump(dumpChildren, indent+1);
|
||||
if (RightChild)
|
||||
RightChild->dump(dumpChildren, indent+1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
InstructionNode::InstructionNode(Instruction* I)
|
||||
: InstrTreeNode(NTInstructionNode, I), codeIsFoldedIntoParent(false)
|
||||
{
|
||||
opLabel = I->getOpcode();
|
||||
|
||||
// Distinguish special cases of some instructions such as Ret and Br
|
||||
//
|
||||
if (opLabel == Instruction::Ret && cast<ReturnInst>(I)->getReturnValue()) {
|
||||
opLabel = RetValueOp; // ret(value) operation
|
||||
}
|
||||
else if (opLabel ==Instruction::Br && !cast<BranchInst>(I)->isUnconditional())
|
||||
{
|
||||
opLabel = BrCondOp; // br(cond) operation
|
||||
} else if (opLabel >= Instruction::SetEQ && opLabel <= Instruction::SetGT) {
|
||||
opLabel = SetCCOp; // common label for all SetCC ops
|
||||
} else if (opLabel == Instruction::Alloca && I->getNumOperands() > 0) {
|
||||
opLabel = AllocaN; // Alloca(ptr, N) operation
|
||||
} else if (opLabel == Instruction::GetElementPtr &&
|
||||
cast<GetElementPtrInst>(I)->hasIndices()) {
|
||||
opLabel = opLabel + 100; // getElem with index vector
|
||||
} else if (opLabel == Instruction::Xor &&
|
||||
BinaryOperator::isNot(I)) {
|
||||
opLabel = (I->getType() == Type::BoolTy)? NotOp // boolean Not operator
|
||||
: BNotOp; // bitwise Not operator
|
||||
} else if (opLabel == Instruction::And || opLabel == Instruction::Or ||
|
||||
opLabel == Instruction::Xor) {
|
||||
// Distinguish bitwise operators from logical operators!
|
||||
if (I->getType() != Type::BoolTy)
|
||||
opLabel = opLabel + 100; // bitwise operator
|
||||
} else if (opLabel == Instruction::Cast) {
|
||||
const Type *ITy = I->getType();
|
||||
switch(ITy->getPrimitiveID())
|
||||
{
|
||||
case Type::BoolTyID: opLabel = ToBoolTy; break;
|
||||
case Type::UByteTyID: opLabel = ToUByteTy; break;
|
||||
case Type::SByteTyID: opLabel = ToSByteTy; break;
|
||||
case Type::UShortTyID: opLabel = ToUShortTy; break;
|
||||
case Type::ShortTyID: opLabel = ToShortTy; break;
|
||||
case Type::UIntTyID: opLabel = ToUIntTy; break;
|
||||
case Type::IntTyID: opLabel = ToIntTy; break;
|
||||
case Type::ULongTyID: opLabel = ToULongTy; break;
|
||||
case Type::LongTyID: opLabel = ToLongTy; break;
|
||||
case Type::FloatTyID: opLabel = ToFloatTy; break;
|
||||
case Type::DoubleTyID: opLabel = ToDoubleTy; break;
|
||||
case Type::ArrayTyID: opLabel = ToArrayTy; break;
|
||||
case Type::PointerTyID: opLabel = ToPointerTy; break;
|
||||
default:
|
||||
// Just use `Cast' opcode otherwise. It's probably ignored.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InstructionNode::dumpNode(int indent) const {
|
||||
for (int i=0; i < indent; i++)
|
||||
std::cerr << " ";
|
||||
std::cerr << getInstruction()->getOpcodeName()
|
||||
<< " [label " << getOpLabel() << "]" << "\n";
|
||||
}
|
||||
|
||||
void
|
||||
VRegListNode::dumpNode(int indent) const {
|
||||
for (int i=0; i < indent; i++)
|
||||
std::cerr << " ";
|
||||
|
||||
std::cerr << "List" << "\n";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
VRegNode::dumpNode(int indent) const {
|
||||
for (int i=0; i < indent; i++)
|
||||
std::cerr << " ";
|
||||
|
||||
std::cerr << "VReg " << getValue() << "\t(type "
|
||||
<< (int) getValue()->getValueType() << ")" << "\n";
|
||||
}
|
||||
|
||||
void
|
||||
ConstantNode::dumpNode(int indent) const {
|
||||
for (int i=0; i < indent; i++)
|
||||
std::cerr << " ";
|
||||
|
||||
std::cerr << "Constant " << getValue() << "\t(type "
|
||||
<< (int) getValue()->getValueType() << ")" << "\n";
|
||||
}
|
||||
|
||||
void LabelNode::dumpNode(int indent) const {
|
||||
for (int i=0; i < indent; i++)
|
||||
std::cerr << " ";
|
||||
|
||||
std::cerr << "Label " << getValue() << "\n";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// class InstrForest
|
||||
//
|
||||
// A forest of instruction trees, usually for a single method.
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
InstrForest::InstrForest(Function *F) {
|
||||
for (Function::iterator BB = F->begin(), FE = F->end(); BB != FE; ++BB) {
|
||||
for(BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
|
||||
buildTreeForInstruction(I);
|
||||
}
|
||||
}
|
||||
|
||||
InstrForest::~InstrForest() {
|
||||
for_each(treeRoots.begin(), treeRoots.end(), deleter<InstructionNode>);
|
||||
}
|
||||
|
||||
void InstrForest::dump() const {
|
||||
for (const_root_iterator I = roots_begin(); I != roots_end(); ++I)
|
||||
(*I)->dump(/*dumpChildren*/ 1, /*indent*/ 0);
|
||||
}
|
||||
|
||||
inline void InstrForest::eraseRoot(InstructionNode* node) {
|
||||
for (RootSet::reverse_iterator RI=treeRoots.rbegin(), RE=treeRoots.rend();
|
||||
RI != RE; ++RI)
|
||||
if (*RI == node)
|
||||
treeRoots.erase(RI.base()-1);
|
||||
}
|
||||
|
||||
inline void InstrForest::noteTreeNodeForInstr(Instruction *instr,
|
||||
InstructionNode *treeNode) {
|
||||
(*this)[instr] = treeNode;
|
||||
treeRoots.push_back(treeNode); // mark node as root of a new tree
|
||||
}
|
||||
|
||||
|
||||
inline void InstrForest::setLeftChild(InstrTreeNode *parent,
|
||||
InstrTreeNode *child) {
|
||||
parent->LeftChild = child;
|
||||
child->Parent = parent;
|
||||
if (InstructionNode* instrNode = dyn_cast<InstructionNode>(child))
|
||||
eraseRoot(instrNode); // no longer a tree root
|
||||
}
|
||||
|
||||
inline void InstrForest::setRightChild(InstrTreeNode *parent,
|
||||
InstrTreeNode *child) {
|
||||
parent->RightChild = child;
|
||||
child->Parent = parent;
|
||||
if (InstructionNode* instrNode = dyn_cast<InstructionNode>(child))
|
||||
eraseRoot(instrNode); // no longer a tree root
|
||||
}
|
||||
|
||||
|
||||
InstructionNode* InstrForest::buildTreeForInstruction(Instruction *instr) {
|
||||
InstructionNode *treeNode = getTreeNodeForInstr(instr);
|
||||
if (treeNode) {
|
||||
// treeNode has already been constructed for this instruction
|
||||
assert(treeNode->getInstruction() == instr);
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
// Otherwise, create a new tree node for this instruction.
|
||||
//
|
||||
treeNode = new InstructionNode(instr);
|
||||
noteTreeNodeForInstr(instr, treeNode);
|
||||
|
||||
if (instr->getOpcode() == Instruction::Call) {
|
||||
// Operands of call instruction
|
||||
return treeNode;
|
||||
}
|
||||
|
||||
// If the instruction has more than 2 instruction operands,
|
||||
// then we need to create artificial list nodes to hold them.
|
||||
// (Note that we only count operands that get tree nodes, and not
|
||||
// others such as branch labels for a branch or switch instruction.)
|
||||
//
|
||||
// To do this efficiently, we'll walk all operands, build treeNodes
|
||||
// for all appropriate operands and save them in an array. We then
|
||||
// insert children at the end, creating list nodes where needed.
|
||||
// As a performance optimization, allocate a child array only
|
||||
// if a fixed array is too small.
|
||||
//
|
||||
int numChildren = 0;
|
||||
InstrTreeNode** childArray = new InstrTreeNode*[instr->getNumOperands()];
|
||||
|
||||
//
|
||||
// Walk the operands of the instruction
|
||||
//
|
||||
for (Instruction::op_iterator O = instr->op_begin(); O!=instr->op_end(); ++O)
|
||||
{
|
||||
Value* operand = *O;
|
||||
|
||||
// Check if the operand is a data value, not an branch label, type,
|
||||
// method or module. If the operand is an address type (i.e., label
|
||||
// or method) that is used in an non-branching operation, e.g., `add'.
|
||||
// that should be considered a data value.
|
||||
|
||||
// Check latter condition here just to simplify the next IF.
|
||||
bool includeAddressOperand =
|
||||
(isa<BasicBlock>(operand) || isa<Function>(operand))
|
||||
&& !instr->isTerminator();
|
||||
|
||||
if (includeAddressOperand || isa<Instruction>(operand) ||
|
||||
isa<Constant>(operand) || isa<Argument>(operand) ||
|
||||
isa<GlobalVariable>(operand))
|
||||
{
|
||||
// This operand is a data value
|
||||
|
||||
// An instruction that computes the incoming value is added as a
|
||||
// child of the current instruction if:
|
||||
// the value has only a single use
|
||||
// AND both instructions are in the same basic block.
|
||||
// AND the current instruction is not a PHI (because the incoming
|
||||
// value is conceptually in a predecessor block,
|
||||
// even though it may be in the same static block)
|
||||
//
|
||||
// (Note that if the value has only a single use (viz., `instr'),
|
||||
// the def of the value can be safely moved just before instr
|
||||
// and therefore it is safe to combine these two instructions.)
|
||||
//
|
||||
// In all other cases, the virtual register holding the value
|
||||
// is used directly, i.e., made a child of the instruction node.
|
||||
//
|
||||
InstrTreeNode* opTreeNode;
|
||||
if (isa<Instruction>(operand) && operand->hasOneUse() &&
|
||||
cast<Instruction>(operand)->getParent() == instr->getParent() &&
|
||||
instr->getOpcode() != Instruction::PHI &&
|
||||
instr->getOpcode() != Instruction::Call)
|
||||
{
|
||||
// Recursively create a treeNode for it.
|
||||
opTreeNode = buildTreeForInstruction((Instruction*)operand);
|
||||
} else if (Constant *CPV = dyn_cast<Constant>(operand)) {
|
||||
// Create a leaf node for a constant
|
||||
opTreeNode = new ConstantNode(CPV);
|
||||
} else {
|
||||
// Create a leaf node for the virtual register
|
||||
opTreeNode = new VRegNode(operand);
|
||||
}
|
||||
|
||||
childArray[numChildren++] = opTreeNode;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Add any selected operands as children in the tree.
|
||||
// Certain instructions can have more than 2 in some instances (viz.,
|
||||
// a CALL or a memory access -- LOAD, STORE, and GetElemPtr -- to an
|
||||
// array or struct). Make the operands of every such instruction into
|
||||
// a right-leaning binary tree with the operand nodes at the leaves
|
||||
// and VRegList nodes as internal nodes.
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
InstrTreeNode *parent = treeNode;
|
||||
|
||||
if (numChildren > 2) {
|
||||
unsigned instrOpcode = treeNode->getInstruction()->getOpcode();
|
||||
assert(instrOpcode == Instruction::PHI ||
|
||||
instrOpcode == Instruction::Call ||
|
||||
instrOpcode == Instruction::Load ||
|
||||
instrOpcode == Instruction::Store ||
|
||||
instrOpcode == Instruction::GetElementPtr);
|
||||
}
|
||||
|
||||
// Insert the first child as a direct child
|
||||
if (numChildren >= 1)
|
||||
setLeftChild(parent, childArray[0]);
|
||||
|
||||
int n;
|
||||
|
||||
// Create a list node for children 2 .. N-1, if any
|
||||
for (n = numChildren-1; n >= 2; n--) {
|
||||
// We have more than two children
|
||||
InstrTreeNode *listNode = new VRegListNode();
|
||||
setRightChild(parent, listNode);
|
||||
setLeftChild(listNode, childArray[numChildren - n]);
|
||||
parent = listNode;
|
||||
}
|
||||
|
||||
// Now insert the last remaining child (if any).
|
||||
if (numChildren >= 2) {
|
||||
assert(n == 1);
|
||||
setRightChild(parent, childArray[numChildren - 1]);
|
||||
}
|
||||
|
||||
delete [] childArray;
|
||||
return treeNode;
|
||||
}
|
|
@ -1,385 +0,0 @@
|
|||
//===- InstrSelection.cpp - Machine Independent Inst Selection Driver -----===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Machine-independent driver file for instruction selection. This file
|
||||
// constructs a forest of BURG instruction trees and then uses the
|
||||
// BURG-generated tree grammar (BURM) to find the optimal instruction sequences
|
||||
// for a given machine.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/iPHINode.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/CodeGen/InstrForest.h"
|
||||
#include "llvm/CodeGen/InstrSelection.h"
|
||||
#include "llvm/CodeGen/InstrSelectionSupport.h"
|
||||
#include "llvm/CodeGen/MachineCodeForInstruction.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetRegInfo.h"
|
||||
#include "Support/CommandLine.h"
|
||||
#include "Support/LeakDetector.h"
|
||||
#include <vector>
|
||||
|
||||
std::vector<MachineInstr*>
|
||||
FixConstantOperandsForInstr(Instruction* vmInstr, MachineInstr* minstr,
|
||||
TargetMachine& target);
|
||||
|
||||
namespace {
|
||||
//===--------------------------------------------------------------------===//
|
||||
// SelectDebugLevel - Allow command line control over debugging.
|
||||
//
|
||||
enum SelectDebugLevel_t {
|
||||
Select_NoDebugInfo,
|
||||
Select_PrintMachineCode,
|
||||
Select_DebugInstTrees,
|
||||
Select_DebugBurgTrees,
|
||||
};
|
||||
|
||||
// Enable Debug Options to be specified on the command line
|
||||
cl::opt<SelectDebugLevel_t>
|
||||
SelectDebugLevel("dselect", cl::Hidden,
|
||||
cl::desc("enable instruction selection debug information"),
|
||||
cl::values(
|
||||
clEnumValN(Select_NoDebugInfo, "n", "disable debug output"),
|
||||
clEnumValN(Select_PrintMachineCode, "y", "print generated machine code"),
|
||||
clEnumValN(Select_DebugInstTrees, "i",
|
||||
"print debugging info for instruction selection"),
|
||||
clEnumValN(Select_DebugBurgTrees, "b", "print burg trees"),
|
||||
0));
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// InstructionSelection Pass
|
||||
//
|
||||
// This is the actual pass object that drives the instruction selection
|
||||
// process.
|
||||
//
|
||||
class InstructionSelection : public FunctionPass {
|
||||
TargetMachine &Target;
|
||||
void InsertCodeForPhis(Function &F);
|
||||
void InsertPhiElimInstructions(BasicBlock *BB,
|
||||
const std::vector<MachineInstr*>& CpVec);
|
||||
void SelectInstructionsForTree(InstrTreeNode* treeRoot, int goalnt);
|
||||
void PostprocessMachineCodeForTree(InstructionNode* instrNode,
|
||||
int ruleForNode, short* nts);
|
||||
public:
|
||||
InstructionSelection(TargetMachine &T) : Target(T) {}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F);
|
||||
virtual const char *getPassName() const { return "Instruction Selection"; }
|
||||
};
|
||||
}
|
||||
|
||||
TmpInstruction::TmpInstruction(MachineCodeForInstruction& mcfi,
|
||||
Value *s1, Value *s2, const std::string &name)
|
||||
: Instruction(s1->getType(), Instruction::UserOp1, name)
|
||||
{
|
||||
mcfi.addTemp(this);
|
||||
|
||||
Operands.push_back(Use(s1, this)); // s1 must be non-null
|
||||
if (s2)
|
||||
Operands.push_back(Use(s2, this));
|
||||
|
||||
// TmpInstructions should not be garbage checked.
|
||||
LeakDetector::removeGarbageObject(this);
|
||||
}
|
||||
|
||||
// Constructor that requires the type of the temporary to be specified.
|
||||
// Both S1 and S2 may be NULL.(
|
||||
TmpInstruction::TmpInstruction(MachineCodeForInstruction& mcfi,
|
||||
const Type *Ty, Value *s1, Value* s2,
|
||||
const std::string &name)
|
||||
: Instruction(Ty, Instruction::UserOp1, name)
|
||||
{
|
||||
mcfi.addTemp(this);
|
||||
|
||||
if (s1)
|
||||
Operands.push_back(Use(s1, this));
|
||||
if (s2)
|
||||
Operands.push_back(Use(s2, this));
|
||||
|
||||
// TmpInstructions should not be garbage checked.
|
||||
LeakDetector::removeGarbageObject(this);
|
||||
}
|
||||
|
||||
|
||||
bool InstructionSelection::runOnFunction(Function &F)
|
||||
{
|
||||
//
|
||||
// Build the instruction trees to be given as inputs to BURG.
|
||||
//
|
||||
InstrForest instrForest(&F);
|
||||
|
||||
if (SelectDebugLevel >= Select_DebugInstTrees) {
|
||||
std::cerr << "\n\n*** Input to instruction selection for function "
|
||||
<< F.getName() << "\n\n" << F
|
||||
<< "\n\n*** Instruction trees for function "
|
||||
<< F.getName() << "\n\n";
|
||||
instrForest.dump();
|
||||
}
|
||||
|
||||
//
|
||||
// Invoke BURG instruction selection for each tree
|
||||
//
|
||||
for (InstrForest::const_root_iterator RI = instrForest.roots_begin();
|
||||
RI != instrForest.roots_end(); ++RI) {
|
||||
InstructionNode* basicNode = *RI;
|
||||
assert(basicNode->parent() == NULL && "A `root' node has a parent?");
|
||||
|
||||
// Invoke BURM to label each tree node with a state
|
||||
burm_label(basicNode);
|
||||
|
||||
if (SelectDebugLevel >= Select_DebugBurgTrees) {
|
||||
printcover(basicNode, 1, 0);
|
||||
std::cerr << "\nCover cost == " << treecost(basicNode, 1, 0) <<"\n\n";
|
||||
printMatches(basicNode);
|
||||
}
|
||||
|
||||
// Then recursively walk the tree to select instructions
|
||||
SelectInstructionsForTree(basicNode, /*goalnt*/1);
|
||||
}
|
||||
|
||||
//
|
||||
// Create the MachineBasicBlock records and add all of the MachineInstrs
|
||||
// defined in the MachineCodeForInstruction objects to also live in the
|
||||
// MachineBasicBlock objects.
|
||||
//
|
||||
MachineFunction &MF = MachineFunction::get(&F);
|
||||
for (Function::iterator BI = F.begin(), BE = F.end(); BI != BE; ++BI) {
|
||||
MachineBasicBlock *MCBB = new MachineBasicBlock(BI);
|
||||
MF.getBasicBlockList().push_back(MCBB);
|
||||
|
||||
for (BasicBlock::iterator II = BI->begin(); II != BI->end(); ++II) {
|
||||
MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(II);
|
||||
MCBB->insert(MCBB->end(), mvec.begin(), mvec.end());
|
||||
}
|
||||
}
|
||||
|
||||
// Insert phi elimination code
|
||||
InsertCodeForPhis(F);
|
||||
|
||||
if (SelectDebugLevel >= Select_PrintMachineCode) {
|
||||
std::cerr << "\n*** Machine instructions after INSTRUCTION SELECTION\n";
|
||||
MachineFunction::get(&F).dump();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// This method inserts phi elimination code for all BBs in a method
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
InstructionSelection::InsertCodeForPhis(Function &F) {
|
||||
// for all basic blocks in function
|
||||
//
|
||||
MachineFunction &MF = MachineFunction::get(&F);
|
||||
for (MachineFunction::iterator BB = MF.begin(); BB != MF.end(); ++BB) {
|
||||
for (BasicBlock::const_iterator IIt = BB->getBasicBlock()->begin();
|
||||
const PHINode *PN = dyn_cast<PHINode>(IIt); ++IIt) {
|
||||
// FIXME: This is probably wrong...
|
||||
Value *PhiCpRes = new PHINode(PN->getType(), "PhiCp:");
|
||||
|
||||
// The leak detector shouldn't track these nodes. They are not garbage,
|
||||
// even though their parent field is never filled in.
|
||||
//
|
||||
LeakDetector::removeGarbageObject(PhiCpRes);
|
||||
|
||||
// for each incoming value of the phi, insert phi elimination
|
||||
//
|
||||
for (unsigned i = 0; i < PN->getNumIncomingValues(); ++i) {
|
||||
// insert the copy instruction to the predecessor BB
|
||||
std::vector<MachineInstr*> mvec, CpVec;
|
||||
Target.getRegInfo().cpValue2Value(PN->getIncomingValue(i), PhiCpRes,
|
||||
mvec);
|
||||
for (std::vector<MachineInstr*>::iterator MI=mvec.begin();
|
||||
MI != mvec.end(); ++MI) {
|
||||
std::vector<MachineInstr*> CpVec2 =
|
||||
FixConstantOperandsForInstr(const_cast<PHINode*>(PN), *MI, Target);
|
||||
CpVec2.push_back(*MI);
|
||||
CpVec.insert(CpVec.end(), CpVec2.begin(), CpVec2.end());
|
||||
}
|
||||
|
||||
InsertPhiElimInstructions(PN->getIncomingBlock(i), CpVec);
|
||||
}
|
||||
|
||||
std::vector<MachineInstr*> mvec;
|
||||
Target.getRegInfo().cpValue2Value(PhiCpRes, const_cast<PHINode*>(PN),
|
||||
mvec);
|
||||
BB->insert(BB->begin(), mvec.begin(), mvec.end());
|
||||
} // for each Phi Instr in BB
|
||||
} // for all BBs in function
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// Thid method inserts a copy instruction to a predecessor BB as a result
|
||||
// of phi elimination.
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
InstructionSelection::InsertPhiElimInstructions(BasicBlock *BB,
|
||||
const std::vector<MachineInstr*>& CpVec)
|
||||
{
|
||||
Instruction *TermInst = (Instruction*)BB->getTerminator();
|
||||
MachineCodeForInstruction &MC4Term = MachineCodeForInstruction::get(TermInst);
|
||||
MachineInstr *FirstMIOfTerm = MC4Term.front();
|
||||
assert (FirstMIOfTerm && "No Machine Instrs for terminator");
|
||||
|
||||
MachineFunction &MF = MachineFunction::get(BB->getParent());
|
||||
|
||||
// FIXME: if PHI instructions existed in the machine code, this would be
|
||||
// unnecessary.
|
||||
MachineBasicBlock *MBB = 0;
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
|
||||
if (I->getBasicBlock() == BB) {
|
||||
MBB = I;
|
||||
break;
|
||||
}
|
||||
|
||||
// find the position of first machine instruction generated by the
|
||||
// terminator of this BB
|
||||
MachineBasicBlock::iterator MCIt =
|
||||
std::find(MBB->begin(), MBB->end(), FirstMIOfTerm);
|
||||
|
||||
assert(MCIt != MBB->end() && "Start inst of terminator not found");
|
||||
|
||||
// insert the copy instructions just before the first machine instruction
|
||||
// generated for the terminator
|
||||
MBB->insert(MCIt, CpVec.begin(), CpVec.end());
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function SelectInstructionsForTree
|
||||
//
|
||||
// Recursively walk the tree to select instructions.
|
||||
// Do this top-down so that child instructions can exploit decisions
|
||||
// made at the child instructions.
|
||||
//
|
||||
// E.g., if br(setle(reg,const)) decides the constant is 0 and uses
|
||||
// a branch-on-integer-register instruction, then the setle node
|
||||
// can use that information to avoid generating the SUBcc instruction.
|
||||
//
|
||||
// Note that this cannot be done bottom-up because setle must do this
|
||||
// only if it is a child of the branch (otherwise, the result of setle
|
||||
// may be used by multiple instructions).
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void
|
||||
InstructionSelection::SelectInstructionsForTree(InstrTreeNode* treeRoot,
|
||||
int goalnt)
|
||||
{
|
||||
// Get the rule that matches this node.
|
||||
//
|
||||
int ruleForNode = burm_rule(treeRoot->state, goalnt);
|
||||
|
||||
if (ruleForNode == 0) {
|
||||
std::cerr << "Could not match instruction tree for instr selection\n";
|
||||
abort();
|
||||
}
|
||||
|
||||
// Get this rule's non-terminals and the corresponding child nodes (if any)
|
||||
//
|
||||
short *nts = burm_nts[ruleForNode];
|
||||
|
||||
// First, select instructions for the current node and rule.
|
||||
// (If this is a list node, not an instruction, then skip this step).
|
||||
// This function is specific to the target architecture.
|
||||
//
|
||||
if (treeRoot->opLabel != VRegListOp) {
|
||||
std::vector<MachineInstr*> minstrVec;
|
||||
|
||||
InstructionNode* instrNode = (InstructionNode*)treeRoot;
|
||||
assert(instrNode->getNodeType() == InstrTreeNode::NTInstructionNode);
|
||||
|
||||
GetInstructionsByRule(instrNode, ruleForNode, nts, Target, minstrVec);
|
||||
|
||||
MachineCodeForInstruction &mvec =
|
||||
MachineCodeForInstruction::get(instrNode->getInstruction());
|
||||
mvec.insert(mvec.end(), minstrVec.begin(), minstrVec.end());
|
||||
}
|
||||
|
||||
// Then, recursively compile the child nodes, if any.
|
||||
//
|
||||
if (nts[0]) {
|
||||
// i.e., there is at least one kid
|
||||
InstrTreeNode* kids[2];
|
||||
int currentRule = ruleForNode;
|
||||
burm_kids(treeRoot, currentRule, kids);
|
||||
|
||||
// First skip over any chain rules so that we don't visit
|
||||
// the current node again.
|
||||
//
|
||||
while (ThisIsAChainRule(currentRule)) {
|
||||
currentRule = burm_rule(treeRoot->state, nts[0]);
|
||||
nts = burm_nts[currentRule];
|
||||
burm_kids(treeRoot, currentRule, kids);
|
||||
}
|
||||
|
||||
// Now we have the first non-chain rule so we have found
|
||||
// the actual child nodes. Recursively compile them.
|
||||
//
|
||||
for (unsigned i = 0; nts[i]; i++) {
|
||||
assert(i < 2);
|
||||
InstrTreeNode::InstrTreeNodeType nodeType = kids[i]->getNodeType();
|
||||
if (nodeType == InstrTreeNode::NTVRegListNode ||
|
||||
nodeType == InstrTreeNode::NTInstructionNode)
|
||||
SelectInstructionsForTree(kids[i], nts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, do any post-processing on this node after its children
|
||||
// have been translated
|
||||
//
|
||||
if (treeRoot->opLabel != VRegListOp)
|
||||
PostprocessMachineCodeForTree((InstructionNode*)treeRoot, ruleForNode, nts);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function PostprocessMachineCodeForTree
|
||||
//
|
||||
// Apply any final cleanups to machine code for the root of a subtree
|
||||
// after selection for all its children has been completed.
|
||||
//
|
||||
void
|
||||
InstructionSelection::PostprocessMachineCodeForTree(InstructionNode* instrNode,
|
||||
int ruleForNode,
|
||||
short* nts)
|
||||
{
|
||||
// Fix up any constant operands in the machine instructions to either
|
||||
// use an immediate field or to load the constant into a register
|
||||
// Walk backwards and use direct indexes to allow insertion before current
|
||||
//
|
||||
Instruction* vmInstr = instrNode->getInstruction();
|
||||
MachineCodeForInstruction &mvec = MachineCodeForInstruction::get(vmInstr);
|
||||
for (unsigned i = mvec.size(); i != 0; --i) {
|
||||
std::vector<MachineInstr*> loadConstVec =
|
||||
FixConstantOperandsForInstr(vmInstr, mvec[i-1], Target);
|
||||
|
||||
mvec.insert(mvec.begin()+i-1, loadConstVec.begin(), loadConstVec.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// createInstructionSelectionPass - Public entrypoint for instruction selection
|
||||
// and this file as a whole...
|
||||
//
|
||||
FunctionPass *createInstructionSelectionPass(TargetMachine &T) {
|
||||
return new InstructionSelection(T);
|
||||
}
|
|
@ -1,259 +0,0 @@
|
|||
//===-- InstrSelectionSupport.cpp -----------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Target-independent instruction selection code. See SparcInstrSelection.cpp
|
||||
// for usage.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CodeGen/InstrSelectionSupport.h"
|
||||
#include "llvm/CodeGen/InstrSelection.h"
|
||||
#include "llvm/CodeGen/MachineInstrAnnot.h"
|
||||
#include "llvm/CodeGen/MachineCodeForInstruction.h"
|
||||
#include "llvm/CodeGen/InstrForest.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetRegInfo.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/BasicBlock.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "../../Target/Sparc/SparcInstrSelectionSupport.h" // FIXME!
|
||||
|
||||
|
||||
// Generate code to load the constant into a TmpInstruction (virtual reg) and
|
||||
// returns the virtual register.
|
||||
//
|
||||
static TmpInstruction*
|
||||
InsertCodeToLoadConstant(Function *F,
|
||||
Value* opValue,
|
||||
Instruction* vmInstr,
|
||||
std::vector<MachineInstr*>& loadConstVec,
|
||||
TargetMachine& target)
|
||||
{
|
||||
// Create a tmp virtual register to hold the constant.
|
||||
MachineCodeForInstruction &mcfi = MachineCodeForInstruction::get(vmInstr);
|
||||
TmpInstruction* tmpReg = new TmpInstruction(mcfi, opValue);
|
||||
|
||||
target.getInstrInfo().CreateCodeToLoadConst(target, F, opValue, tmpReg,
|
||||
loadConstVec, mcfi);
|
||||
|
||||
// Record the mapping from the tmp VM instruction to machine instruction.
|
||||
// Do this for all machine instructions that were not mapped to any
|
||||
// other temp values created by
|
||||
// tmpReg->addMachineInstruction(loadConstVec.back());
|
||||
|
||||
return tmpReg;
|
||||
}
|
||||
|
||||
|
||||
MachineOperand::MachineOperandType
|
||||
ChooseRegOrImmed(int64_t intValue,
|
||||
bool isSigned,
|
||||
MachineOpCode opCode,
|
||||
const TargetMachine& target,
|
||||
bool canUseImmed,
|
||||
unsigned int& getMachineRegNum,
|
||||
int64_t& getImmedValue)
|
||||
{
|
||||
MachineOperand::MachineOperandType opType=MachineOperand::MO_VirtualRegister;
|
||||
getMachineRegNum = 0;
|
||||
getImmedValue = 0;
|
||||
|
||||
if (canUseImmed &&
|
||||
target.getInstrInfo().constantFitsInImmedField(opCode, intValue)) {
|
||||
opType = isSigned? MachineOperand::MO_SignExtendedImmed
|
||||
: MachineOperand::MO_UnextendedImmed;
|
||||
getImmedValue = intValue;
|
||||
} else if (intValue == 0 && target.getRegInfo().getZeroRegNum() >= 0) {
|
||||
opType = MachineOperand::MO_MachineRegister;
|
||||
getMachineRegNum = target.getRegInfo().getZeroRegNum();
|
||||
}
|
||||
|
||||
return opType;
|
||||
}
|
||||
|
||||
|
||||
MachineOperand::MachineOperandType
|
||||
ChooseRegOrImmed(Value* val,
|
||||
MachineOpCode opCode,
|
||||
const TargetMachine& target,
|
||||
bool canUseImmed,
|
||||
unsigned int& getMachineRegNum,
|
||||
int64_t& getImmedValue)
|
||||
{
|
||||
getMachineRegNum = 0;
|
||||
getImmedValue = 0;
|
||||
|
||||
// To use reg or immed, constant needs to be integer, bool, or a NULL pointer
|
||||
// TargetInstrInfo::ConvertConstantToIntType() does the right conversions:
|
||||
bool isValidConstant;
|
||||
uint64_t valueToUse =
|
||||
target.getInstrInfo().ConvertConstantToIntType(target, val, val->getType(),
|
||||
isValidConstant);
|
||||
if (! isValidConstant)
|
||||
return MachineOperand::MO_VirtualRegister;
|
||||
|
||||
// Now check if the constant value fits in the IMMED field.
|
||||
//
|
||||
return ChooseRegOrImmed((int64_t) valueToUse, val->getType()->isSigned(),
|
||||
opCode, target, canUseImmed,
|
||||
getMachineRegNum, getImmedValue);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Function: FixConstantOperandsForInstr
|
||||
//
|
||||
// Purpose:
|
||||
// Special handling for constant operands of a machine instruction
|
||||
// -- if the constant is 0, use the hardwired 0 register, if any;
|
||||
// -- if the constant fits in the IMMEDIATE field, use that field;
|
||||
// -- else create instructions to put the constant into a register, either
|
||||
// directly or by loading explicitly from the constant pool.
|
||||
//
|
||||
// In the first 2 cases, the operand of `minstr' is modified in place.
|
||||
// Returns a vector of machine instructions generated for operands that
|
||||
// fall under case 3; these must be inserted before `minstr'.
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
std::vector<MachineInstr*>
|
||||
FixConstantOperandsForInstr(Instruction* vmInstr,
|
||||
MachineInstr* minstr,
|
||||
TargetMachine& target)
|
||||
{
|
||||
std::vector<MachineInstr*> MVec;
|
||||
|
||||
MachineOpCode opCode = minstr->getOpCode();
|
||||
const TargetInstrInfo& instrInfo = target.getInstrInfo();
|
||||
int resultPos = instrInfo.getResultPos(opCode);
|
||||
int immedPos = instrInfo.getImmedConstantPos(opCode);
|
||||
|
||||
Function *F = vmInstr->getParent()->getParent();
|
||||
|
||||
for (unsigned op=0; op < minstr->getNumOperands(); op++)
|
||||
{
|
||||
const MachineOperand& mop = minstr->getOperand(op);
|
||||
|
||||
// Skip the result position, preallocated machine registers, or operands
|
||||
// that cannot be constants (CC regs or PC-relative displacements)
|
||||
if (resultPos == (int)op ||
|
||||
mop.getType() == MachineOperand::MO_MachineRegister ||
|
||||
mop.getType() == MachineOperand::MO_CCRegister ||
|
||||
mop.getType() == MachineOperand::MO_PCRelativeDisp)
|
||||
continue;
|
||||
|
||||
bool constantThatMustBeLoaded = false;
|
||||
unsigned int machineRegNum = 0;
|
||||
int64_t immedValue = 0;
|
||||
Value* opValue = NULL;
|
||||
MachineOperand::MachineOperandType opType =
|
||||
MachineOperand::MO_VirtualRegister;
|
||||
|
||||
// Operand may be a virtual register or a compile-time constant
|
||||
if (mop.getType() == MachineOperand::MO_VirtualRegister) {
|
||||
assert(mop.getVRegValue() != NULL);
|
||||
opValue = mop.getVRegValue();
|
||||
if (Constant *opConst = dyn_cast<Constant>(opValue)) {
|
||||
opType = ChooseRegOrImmed(opConst, opCode, target,
|
||||
(immedPos == (int)op), machineRegNum,
|
||||
immedValue);
|
||||
if (opType == MachineOperand::MO_VirtualRegister)
|
||||
constantThatMustBeLoaded = true;
|
||||
}
|
||||
} else {
|
||||
assert(mop.isImmediate());
|
||||
bool isSigned = mop.getType() == MachineOperand::MO_SignExtendedImmed;
|
||||
|
||||
// Bit-selection flags indicate an instruction that is extracting
|
||||
// bits from its operand so ignore this even if it is a big constant.
|
||||
if (mop.opHiBits32() || mop.opLoBits32() ||
|
||||
mop.opHiBits64() || mop.opLoBits64())
|
||||
continue;
|
||||
|
||||
opType = ChooseRegOrImmed(mop.getImmedValue(), isSigned,
|
||||
opCode, target, (immedPos == (int)op),
|
||||
machineRegNum, immedValue);
|
||||
|
||||
if (opType == MachineOperand::MO_SignExtendedImmed ||
|
||||
opType == MachineOperand::MO_UnextendedImmed) {
|
||||
// The optype is an immediate value
|
||||
// This means we need to change the opcode, e.g. ADDr -> ADDi
|
||||
unsigned newOpcode = convertOpcodeFromRegToImm(opCode);
|
||||
minstr->setOpcode(newOpcode);
|
||||
}
|
||||
|
||||
if (opType == mop.getType())
|
||||
continue; // no change: this is the most common case
|
||||
|
||||
if (opType == MachineOperand::MO_VirtualRegister) {
|
||||
constantThatMustBeLoaded = true;
|
||||
opValue = isSigned
|
||||
? (Value*)ConstantSInt::get(Type::LongTy, immedValue)
|
||||
: (Value*)ConstantUInt::get(Type::ULongTy,(uint64_t)immedValue);
|
||||
}
|
||||
}
|
||||
|
||||
if (opType == MachineOperand::MO_MachineRegister)
|
||||
minstr->SetMachineOperandReg(op, machineRegNum);
|
||||
else if (opType == MachineOperand::MO_SignExtendedImmed ||
|
||||
opType == MachineOperand::MO_UnextendedImmed) {
|
||||
minstr->SetMachineOperandConst(op, opType, immedValue);
|
||||
// The optype is or has become an immediate
|
||||
// This means we need to change the opcode, e.g. ADDr -> ADDi
|
||||
unsigned newOpcode = convertOpcodeFromRegToImm(opCode);
|
||||
minstr->setOpcode(newOpcode);
|
||||
} else if (constantThatMustBeLoaded ||
|
||||
(opValue && isa<GlobalValue>(opValue)))
|
||||
{ // opValue is a constant that must be explicitly loaded into a reg
|
||||
assert(opValue);
|
||||
TmpInstruction* tmpReg = InsertCodeToLoadConstant(F, opValue, vmInstr,
|
||||
MVec, target);
|
||||
minstr->SetMachineOperandVal(op, MachineOperand::MO_VirtualRegister,
|
||||
tmpReg);
|
||||
}
|
||||
}
|
||||
|
||||
// Also, check for implicit operands used by the machine instruction
|
||||
// (no need to check those defined since they cannot be constants).
|
||||
// These include:
|
||||
// -- arguments to a Call
|
||||
// -- return value of a Return
|
||||
// Any such operand that is a constant value needs to be fixed also.
|
||||
// The current instructions with implicit refs (viz., Call and Return)
|
||||
// have no immediate fields, so the constant always needs to be loaded
|
||||
// into a register.
|
||||
//
|
||||
bool isCall = instrInfo.isCall(opCode);
|
||||
unsigned lastCallArgNum = 0; // unused if not a call
|
||||
CallArgsDescriptor* argDesc = NULL; // unused if not a call
|
||||
if (isCall)
|
||||
argDesc = CallArgsDescriptor::get(minstr);
|
||||
|
||||
for (unsigned i=0, N=minstr->getNumImplicitRefs(); i < N; ++i)
|
||||
if (isa<Constant>(minstr->getImplicitRef(i)) ||
|
||||
isa<GlobalValue>(minstr->getImplicitRef(i)))
|
||||
{
|
||||
Value* oldVal = minstr->getImplicitRef(i);
|
||||
TmpInstruction* tmpReg =
|
||||
InsertCodeToLoadConstant(F, oldVal, vmInstr, MVec, target);
|
||||
minstr->setImplicitRef(i, tmpReg);
|
||||
|
||||
if (isCall) {
|
||||
// find and replace the argument in the CallArgsDescriptor
|
||||
unsigned i=lastCallArgNum;
|
||||
while (argDesc->getArgInfo(i).getArgVal() != oldVal)
|
||||
++i;
|
||||
assert(i < argDesc->getNumArgs() &&
|
||||
"Constant operands to a call *must* be in the arg list");
|
||||
lastCallArgNum = i;
|
||||
argDesc->getArgInfo(i).replaceArgVal(tmpReg);
|
||||
}
|
||||
}
|
||||
|
||||
return MVec;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
##===- lib/CodeGen/InstrSelection/Makefile -----------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file was developed by the LLVM research group and is distributed under
|
||||
# the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../..
|
||||
|
||||
DIRS =
|
||||
|
||||
LIBRARYNAME = select
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
|
@ -1,58 +0,0 @@
|
|||
//===-- IGNode.cpp --------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements an Interference graph node for coloring-based register
|
||||
// allocation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IGNode.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Sets this IGNode on stack and reduce the degree of neighbors
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void IGNode::pushOnStack() {
|
||||
OnStack = true;
|
||||
int neighs = AdjList.size();
|
||||
|
||||
if (neighs < 0) {
|
||||
std::cerr << "\nAdj List size = " << neighs;
|
||||
assert(0 && "Invalid adj list size");
|
||||
}
|
||||
|
||||
for (int i=0; i < neighs; i++)
|
||||
AdjList[i]->decCurDegree();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Deletes an adjacency node. IGNodes are deleted when coalescing merges
|
||||
// two IGNodes together.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void IGNode::delAdjIGNode(const IGNode *Node) {
|
||||
std::vector<IGNode *>::iterator It=find(AdjList.begin(), AdjList.end(), Node);
|
||||
assert(It != AdjList.end() && "The node must be there!");
|
||||
AdjList.erase(It);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Get the number of unique neighbors if these two nodes are merged
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
unsigned
|
||||
IGNode::getCombinedDegree(const IGNode* otherNode) const {
|
||||
std::vector<IGNode*> nbrs(AdjList);
|
||||
nbrs.insert(nbrs.end(), otherNode->AdjList.begin(), otherNode->AdjList.end());
|
||||
sort(nbrs.begin(), nbrs.end());
|
||||
std::vector<IGNode*>::iterator new_end = unique(nbrs.begin(), nbrs.end());
|
||||
return new_end - nbrs.begin();
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
//===-- IGNode.h - Represent a node in an interference graph ----*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file represents a node in an interference graph.
|
||||
//
|
||||
// For efficiency, the AdjList is updated only once - ie. we can add but not
|
||||
// remove nodes from AdjList.
|
||||
//
|
||||
// The removal of nodes from IG is simulated by decrementing the CurDegree.
|
||||
// If this node is put on stack (that is removed from IG), the CurDegree of all
|
||||
// the neighbors are decremented and this node is marked OnStack. Hence
|
||||
// the effective neighbors in the AdjList are the ones that do not have the
|
||||
// OnStack flag set (therefore, they are in the IG).
|
||||
//
|
||||
// The methods that modify/use the CurDegree must be called only
|
||||
// after all modifications to the IG are over (i.e., all neighbors are fixed).
|
||||
//
|
||||
// The vector representation is the most efficient one for adj list.
|
||||
// Though nodes are removed when coalescing is done, we access it in sequence
|
||||
// for far many times when coloring (colorNode()).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef IGNODE_H
|
||||
#define IGNODE_H
|
||||
|
||||
#include "LiveRange.h"
|
||||
#include <vector>
|
||||
class RegClass;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Class IGNode
|
||||
//
|
||||
// Represents a node in an interference graph.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class IGNode {
|
||||
const unsigned Index; // index within IGNodeList
|
||||
bool OnStack; // this has been pushed on to stack for coloring
|
||||
std::vector<IGNode *> AdjList;// adjacency list for this live range
|
||||
|
||||
int CurDegree;
|
||||
//
|
||||
// set by InterferenceGraph::setCurDegreeOfIGNodes() after calculating
|
||||
// all adjacency lists.
|
||||
// Decremented when a neighbor is pushed on to the stack.
|
||||
// After that, never incremented/set again nor used.
|
||||
|
||||
LiveRange *const ParentLR;
|
||||
public:
|
||||
|
||||
IGNode(LiveRange *LR, unsigned index) : Index(index), ParentLR(LR) {
|
||||
OnStack = false;
|
||||
CurDegree = -1;
|
||||
ParentLR->setUserIGNode(this);
|
||||
}
|
||||
|
||||
inline unsigned int getIndex() const { return Index; }
|
||||
|
||||
// adjLists must be updated only once. However, the CurDegree can be changed
|
||||
//
|
||||
inline void addAdjIGNode(IGNode *AdjNode) { AdjList.push_back(AdjNode); }
|
||||
|
||||
inline IGNode *getAdjIGNode(unsigned ind) const
|
||||
{ assert ( ind < AdjList.size()); return AdjList[ind]; }
|
||||
|
||||
// delete a node in AdjList - node must be in the list
|
||||
// should not be called often
|
||||
//
|
||||
void delAdjIGNode(const IGNode *Node);
|
||||
|
||||
inline unsigned getNumOfNeighbors() const { return AdjList.size(); }
|
||||
|
||||
// Get the number of unique neighbors if these two nodes are merged
|
||||
unsigned getCombinedDegree(const IGNode* otherNode) const;
|
||||
|
||||
inline bool isOnStack() const { return OnStack; }
|
||||
|
||||
// remove form IG and pushes on to stack (reduce the degree of neighbors)
|
||||
//
|
||||
void pushOnStack();
|
||||
|
||||
// CurDegree is the effective number of neighbors when neighbors are
|
||||
// pushed on to the stack during the coloring phase. Must be called
|
||||
// after all modifications to the IG are over (i.e., all neighbors are
|
||||
// fixed).
|
||||
//
|
||||
inline void setCurDegree() {
|
||||
assert(CurDegree == -1);
|
||||
CurDegree = AdjList.size();
|
||||
}
|
||||
|
||||
inline int getCurDegree() const { return CurDegree; }
|
||||
|
||||
// called when a neigh is pushed on to stack
|
||||
//
|
||||
inline void decCurDegree() { assert(CurDegree > 0); --CurDegree; }
|
||||
|
||||
// The following methods call the methods in ParentLR
|
||||
// They are added to this class for convenience
|
||||
// If many of these are called within a single scope,
|
||||
// consider calling the methods directly on LR
|
||||
inline bool hasColor() const { return ParentLR->hasColor(); }
|
||||
|
||||
inline unsigned int getColor() const { return ParentLR->getColor(); }
|
||||
|
||||
inline void setColor(unsigned Col) { ParentLR->setColor(Col); }
|
||||
|
||||
inline LiveRange *getParentLR() const { return ParentLR; }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,248 +0,0 @@
|
|||
//===-- InterferenceGraph.cpp ---------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Interference graph for coloring-based register allocation for LLVM.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IGNode.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include "RegAllocCommon.h"
|
||||
#include "Support/STLExtras.h"
|
||||
#include <algorithm>
|
||||
|
||||
// for asserting this IG node is infact in the IGNodeList of this class
|
||||
inline static void assertIGNode(const InterferenceGraph *IG,
|
||||
const IGNode *Node) {
|
||||
assert(IG->getIGNodeList()[Node->getIndex()] == Node);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Constructor: Records the RegClass and initalizes IGNodeList.
|
||||
// The matrix is NOT yet created by the constructor. Call createGraph()
|
||||
// to create it after adding all IGNodes to the IGNodeList.
|
||||
//-----------------------------------------------------------------------------
|
||||
InterferenceGraph::InterferenceGraph(RegClass *const RC) : RegCl(RC) {
|
||||
IG = NULL;
|
||||
Size = 0;
|
||||
if( DEBUG_RA >= RA_DEBUG_Interference)
|
||||
std::cerr << "Interference graph created!\n";
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// destructor. Deletes the bit matrix and all IGNodes
|
||||
//-----------------------------------------------------------------------------
|
||||
InterferenceGraph:: ~InterferenceGraph() {
|
||||
// delete the matrix
|
||||
for(unsigned int r=0; r < IGNodeList.size(); ++r)
|
||||
delete[] IG[r];
|
||||
delete[] IG;
|
||||
|
||||
// delete all IGNodes in the IGNodeList
|
||||
for_each(IGNodeList.begin(), IGNodeList.end(), deleter<IGNode>);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Creates (dynamically allocates) the bit matrix necessary to hold the
|
||||
// interference graph.
|
||||
//-----------------------------------------------------------------------------
|
||||
void InterferenceGraph::createGraph()
|
||||
{
|
||||
Size = IGNodeList.size();
|
||||
IG = new char*[Size];
|
||||
for( unsigned int r=0; r < Size; ++r)
|
||||
IG[r] = new char[Size];
|
||||
|
||||
// init IG matrix
|
||||
for(unsigned int i=0; i < Size; i++)
|
||||
for(unsigned int j=0; j < Size; j++)
|
||||
IG[i][j] = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// creates a new IGNode for the given live range and add to IG
|
||||
//-----------------------------------------------------------------------------
|
||||
void InterferenceGraph::addLRToIG(LiveRange *const LR)
|
||||
{
|
||||
IGNodeList.push_back(new IGNode(LR, IGNodeList.size()));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// set interference for two live ranges
|
||||
// update both the matrix and AdjLists of nodes.
|
||||
// If there is already an interference between LR1 and LR2, adj lists
|
||||
// are not updated. LR1 and LR2 must be distinct since if not, it suggests
|
||||
// that there is some wrong logic in some other method.
|
||||
//-----------------------------------------------------------------------------
|
||||
void InterferenceGraph::setInterference(const LiveRange *const LR1,
|
||||
const LiveRange *const LR2 ) {
|
||||
assert(LR1 != LR2);
|
||||
|
||||
IGNode *IGNode1 = LR1->getUserIGNode();
|
||||
IGNode *IGNode2 = LR2->getUserIGNode();
|
||||
|
||||
assertIGNode(this, IGNode1);
|
||||
assertIGNode(this, IGNode2);
|
||||
|
||||
unsigned row = IGNode1->getIndex();
|
||||
unsigned col = IGNode2->getIndex();
|
||||
|
||||
char *val;
|
||||
|
||||
if( DEBUG_RA >= RA_DEBUG_Interference)
|
||||
std::cerr << "setting intf for: [" << row << "][" << col << "]\n";
|
||||
|
||||
( row > col) ? val = &IG[row][col]: val = &IG[col][row];
|
||||
|
||||
if( ! (*val) ) { // if this interf is not previously set
|
||||
*val = 1; // add edges between nodes
|
||||
IGNode1->addAdjIGNode( IGNode2 );
|
||||
IGNode2->addAdjIGNode( IGNode1 );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// return whether two live ranges interfere
|
||||
//----------------------------------------------------------------------------
|
||||
unsigned InterferenceGraph::getInterference(const LiveRange *const LR1,
|
||||
const LiveRange *const LR2) const {
|
||||
assert(LR1 != LR2);
|
||||
assertIGNode(this, LR1->getUserIGNode());
|
||||
assertIGNode(this, LR2->getUserIGNode());
|
||||
|
||||
const unsigned int row = LR1->getUserIGNode()->getIndex();
|
||||
const unsigned int col = LR2->getUserIGNode()->getIndex();
|
||||
|
||||
char ret;
|
||||
if (row > col)
|
||||
ret = IG[row][col];
|
||||
else
|
||||
ret = IG[col][row];
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Merge 2 IGNodes. The neighbors of the SrcNode will be added to the DestNode.
|
||||
// Then the IGNode2L will be deleted. Necessary for coalescing.
|
||||
// IMPORTANT: The live ranges are NOT merged by this method. Use
|
||||
// LiveRangeInfo::unionAndUpdateLRs for that purpose.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void InterferenceGraph::mergeIGNodesOfLRs(const LiveRange *LR1,
|
||||
LiveRange *LR2) {
|
||||
|
||||
assert( LR1 != LR2); // cannot merge the same live range
|
||||
|
||||
IGNode *const DestNode = LR1->getUserIGNode();
|
||||
IGNode *SrcNode = LR2->getUserIGNode();
|
||||
|
||||
assertIGNode(this, DestNode);
|
||||
assertIGNode(this, SrcNode);
|
||||
|
||||
if( DEBUG_RA >= RA_DEBUG_Interference) {
|
||||
std::cerr << "Merging LRs: \""; printSet(*LR1);
|
||||
std::cerr << "\" and \""; printSet(*LR2);
|
||||
std::cerr << "\"\n";
|
||||
}
|
||||
|
||||
unsigned SrcDegree = SrcNode->getNumOfNeighbors();
|
||||
const unsigned SrcInd = SrcNode->getIndex();
|
||||
|
||||
|
||||
// for all neighs of SrcNode
|
||||
for(unsigned i=0; i < SrcDegree; i++) {
|
||||
IGNode *NeighNode = SrcNode->getAdjIGNode(i);
|
||||
|
||||
LiveRange *const LROfNeigh = NeighNode->getParentLR();
|
||||
|
||||
// delete edge between src and neigh - even neigh == dest
|
||||
NeighNode->delAdjIGNode(SrcNode);
|
||||
|
||||
// set the matrix posn to 0 betn src and neigh - even neigh == dest
|
||||
const unsigned NInd = NeighNode->getIndex();
|
||||
( SrcInd > NInd) ? (IG[SrcInd][NInd]=0) : (IG[NInd][SrcInd]=0) ;
|
||||
|
||||
|
||||
if( LR1 != LROfNeigh) { // if the neigh != dest
|
||||
|
||||
// add edge betwn Dest and Neigh - if there is no current edge
|
||||
setInterference(LR1, LROfNeigh );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
IGNodeList[ SrcInd ] = NULL;
|
||||
|
||||
// SrcNode is no longer necessary - LR2 must be deleted by the caller
|
||||
delete( SrcNode );
|
||||
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// must be called after modifications to the graph are over but before
|
||||
// pushing IGNodes on to the stack for coloring.
|
||||
//----------------------------------------------------------------------------
|
||||
void InterferenceGraph::setCurDegreeOfIGNodes()
|
||||
{
|
||||
unsigned Size = IGNodeList.size();
|
||||
|
||||
for( unsigned i=0; i < Size; i++) {
|
||||
IGNode *Node = IGNodeList[i];
|
||||
if( Node )
|
||||
Node->setCurDegree();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------- debugging (Printing) methods -----------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Print the IGnodes
|
||||
//----------------------------------------------------------------------------
|
||||
void InterferenceGraph::printIG() const {
|
||||
for(unsigned i=0; i < Size; i++) {
|
||||
const IGNode *const Node = IGNodeList[i];
|
||||
if(Node) {
|
||||
std::cerr << " [" << i << "] ";
|
||||
|
||||
for( unsigned int j=0; j < Size; j++)
|
||||
if(IG[i][j])
|
||||
std::cerr << "(" << i << "," << j << ") ";
|
||||
std::cerr << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Print the IGnodes in the IGNode List
|
||||
//----------------------------------------------------------------------------
|
||||
void InterferenceGraph::printIGNodeList() const {
|
||||
for(unsigned i=0; i < IGNodeList.size() ; ++i) {
|
||||
const IGNode *const Node = IGNodeList[i];
|
||||
|
||||
if (Node) {
|
||||
std::cerr << " [" << Node->getIndex() << "] ";
|
||||
printSet(*Node->getParentLR());
|
||||
//int Deg = Node->getCurDegree();
|
||||
std::cerr << "\t <# of Neighs: " << Node->getNumOfNeighbors() << ">\n";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
//===-- InterferenceGraph.h - Interference graph for register coloring -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Title: InterferenceGraph.h -*- C++ -*-
|
||||
Author: Ruchira Sasanka
|
||||
Date: July 20, 01
|
||||
Purpose: Interference Graph used for register coloring.
|
||||
|
||||
Notes:
|
||||
Adj Info is stored in the lower trangular matrix (i.e., row > col )
|
||||
|
||||
This class must be used in the following way:
|
||||
|
||||
* Construct class
|
||||
* call addLRToIG as many times to add ALL LRs to this IG
|
||||
* call createGraph to create the actual matrix
|
||||
* Then setInterference, getInterference, mergeIGNodesOfLRs can be
|
||||
called as desired to modify the graph.
|
||||
* Once the modifications to the graph are over, call
|
||||
setCurDegreeOfIGNodes() before pushing IGNodes on to stack for coloring.
|
||||
*/
|
||||
|
||||
#ifndef INTERFERENCEGRAPH_H
|
||||
#define INTERFERENCEGRAPH_H
|
||||
|
||||
#include <vector>
|
||||
class LiveRange;
|
||||
class RegClass;
|
||||
class IGNode;
|
||||
|
||||
class InterferenceGraph {
|
||||
char **IG; // a poiner to the interference graph
|
||||
unsigned int Size; // size of a side of the IG
|
||||
RegClass *const RegCl; // RegCl contains this IG
|
||||
std::vector<IGNode *> IGNodeList; // a list of all IGNodes in a reg class
|
||||
|
||||
public:
|
||||
// the matrix is not yet created by the constructor. Call createGraph()
|
||||
// to create it after adding all IGNodes to the IGNodeList
|
||||
InterferenceGraph(RegClass *RC);
|
||||
~InterferenceGraph();
|
||||
|
||||
void createGraph();
|
||||
|
||||
void addLRToIG(LiveRange *LR);
|
||||
|
||||
void setInterference(const LiveRange *LR1,
|
||||
const LiveRange *LR2);
|
||||
|
||||
unsigned getInterference(const LiveRange *LR1,
|
||||
const LiveRange *LR2) const ;
|
||||
|
||||
void mergeIGNodesOfLRs(const LiveRange *LR1, LiveRange *LR2);
|
||||
|
||||
std::vector<IGNode *> &getIGNodeList() { return IGNodeList; }
|
||||
const std::vector<IGNode *> &getIGNodeList() const { return IGNodeList; }
|
||||
|
||||
void setCurDegreeOfIGNodes();
|
||||
|
||||
void printIG() const;
|
||||
void printIGNodeList() const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,180 +0,0 @@
|
|||
//===-- LiveRange.h - Store info about a live range -------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Implements a live range using a ValueSet. A LiveRange is a simple set
|
||||
// of Values.
|
||||
//
|
||||
// Since the Value pointed by a use is the same as of its def, it is sufficient
|
||||
// to keep only defs in a LiveRange.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LIVERANGE_H
|
||||
#define LIVERANGE_H
|
||||
|
||||
#include "llvm/Value.h"
|
||||
#include "llvm/CodeGen/ValueSet.h"
|
||||
|
||||
class RegClass;
|
||||
class IGNode;
|
||||
|
||||
class LiveRange : public ValueSet {
|
||||
RegClass *MyRegClass; // register class (e.g., int, FP) for this LR
|
||||
|
||||
/// doesSpanAcrossCalls - Does this live range span across calls?
|
||||
/// This information is used by graph coloring algo to avoid allocating
|
||||
/// volatile colors to live ranges that span across calls (since they have to
|
||||
/// be saved/restored)
|
||||
///
|
||||
bool doesSpanAcrossCalls;
|
||||
|
||||
IGNode *UserIGNode; // IGNode which uses this LR
|
||||
int Color; // color assigned to this live range
|
||||
bool mustSpill; // whether this LR must be spilt
|
||||
|
||||
/// mustSaveAcrossCalls - whether this LR must be saved accross calls
|
||||
/// ***TODO REMOVE this
|
||||
///
|
||||
bool mustSaveAcrossCalls;
|
||||
|
||||
/// SuggestedColor - if this LR has a suggested color, can it be
|
||||
/// really alloated? A suggested color cannot be allocated when the
|
||||
/// suggested color is volatile and when there are call
|
||||
/// interferences.
|
||||
///
|
||||
int SuggestedColor; // The suggested color for this LR
|
||||
|
||||
/// CanUseSuggestedCol - It is possible that a suggested color for
|
||||
/// this live range is not available before graph coloring (e.g., it
|
||||
/// can be allocated to another live range which interferes with
|
||||
/// this)
|
||||
///
|
||||
bool CanUseSuggestedCol;
|
||||
|
||||
/// SpilledStackOffsetFromFP - If this LR is spilled, its stack
|
||||
/// offset from *FP*. The spilled offsets must always be relative to
|
||||
/// the FP.
|
||||
///
|
||||
int SpilledStackOffsetFromFP;
|
||||
|
||||
/// HasSpillOffset 0 Whether this live range has a spill offset
|
||||
///
|
||||
bool HasSpillOffset;
|
||||
|
||||
/// The spill cost of this live range. Calculated using loop depth of
|
||||
/// each reference to each Value in the live range
|
||||
///
|
||||
unsigned SpillCost;
|
||||
|
||||
public:
|
||||
LiveRange() {
|
||||
Color = SuggestedColor = -1; // not yet colored
|
||||
mustSpill = mustSaveAcrossCalls = false;
|
||||
MyRegClass = 0;
|
||||
UserIGNode = 0;
|
||||
doesSpanAcrossCalls = false;
|
||||
CanUseSuggestedCol = true;
|
||||
HasSpillOffset = false;
|
||||
SpillCost = 0;
|
||||
}
|
||||
|
||||
void setRegClass(RegClass *RC) { MyRegClass = RC; }
|
||||
|
||||
RegClass *getRegClass() const { assert(MyRegClass); return MyRegClass; }
|
||||
unsigned getRegClassID() const;
|
||||
|
||||
bool hasColor() const { return Color != -1; }
|
||||
|
||||
unsigned getColor() const { assert(Color != -1); return (unsigned)Color; }
|
||||
|
||||
void setColor(unsigned Col) { Color = (int)Col; }
|
||||
|
||||
inline void setCallInterference() {
|
||||
doesSpanAcrossCalls = 1;
|
||||
}
|
||||
inline void clearCallInterference() {
|
||||
doesSpanAcrossCalls = 0;
|
||||
}
|
||||
|
||||
inline bool isCallInterference() const {
|
||||
return doesSpanAcrossCalls == 1;
|
||||
}
|
||||
|
||||
inline void markForSpill() { mustSpill = true; }
|
||||
|
||||
inline bool isMarkedForSpill() const { return mustSpill; }
|
||||
|
||||
inline void setSpillOffFromFP(int StackOffset) {
|
||||
assert(mustSpill && "This LR is not spilled");
|
||||
SpilledStackOffsetFromFP = StackOffset;
|
||||
HasSpillOffset = true;
|
||||
}
|
||||
|
||||
inline void modifySpillOffFromFP(int StackOffset) {
|
||||
assert(mustSpill && "This LR is not spilled");
|
||||
SpilledStackOffsetFromFP = StackOffset;
|
||||
HasSpillOffset = true;
|
||||
}
|
||||
|
||||
inline bool hasSpillOffset() const {
|
||||
return HasSpillOffset;
|
||||
}
|
||||
|
||||
inline int getSpillOffFromFP() const {
|
||||
assert(HasSpillOffset && "This LR is not spilled");
|
||||
return SpilledStackOffsetFromFP;
|
||||
}
|
||||
|
||||
inline void markForSaveAcrossCalls() { mustSaveAcrossCalls = true; }
|
||||
|
||||
inline void setUserIGNode(IGNode *IGN) {
|
||||
assert(!UserIGNode); UserIGNode = IGN;
|
||||
}
|
||||
|
||||
// getUserIGNode - NULL if the user is not allocated
|
||||
inline IGNode *getUserIGNode() const { return UserIGNode; }
|
||||
|
||||
inline const Type *getType() const {
|
||||
return (*begin())->getType(); // set's don't have a front
|
||||
}
|
||||
|
||||
inline void setSuggestedColor(int Col) {
|
||||
if (SuggestedColor == -1)
|
||||
SuggestedColor = Col;
|
||||
}
|
||||
|
||||
inline unsigned getSuggestedColor() const {
|
||||
assert(SuggestedColor != -1); // only a valid color is obtained
|
||||
return (unsigned)SuggestedColor;
|
||||
}
|
||||
|
||||
inline bool hasSuggestedColor() const {
|
||||
return SuggestedColor != -1;
|
||||
}
|
||||
|
||||
inline bool isSuggestedColorUsable() const {
|
||||
assert(hasSuggestedColor() && "No suggested color");
|
||||
return CanUseSuggestedCol;
|
||||
}
|
||||
|
||||
inline void setSuggestedColorUsable(bool val) {
|
||||
assert(hasSuggestedColor() && "No suggested color");
|
||||
CanUseSuggestedCol = val;
|
||||
}
|
||||
|
||||
inline void addSpillCost(unsigned cost) {
|
||||
SpillCost += cost;
|
||||
}
|
||||
|
||||
inline unsigned getSpillCost() const {
|
||||
return SpillCost;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,413 +0,0 @@
|
|||
//===-- LiveRangeInfo.cpp -------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Live range construction for coloring-based register allocation for LLVM.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IGNode.h"
|
||||
#include "LiveRangeInfo.h"
|
||||
#include "RegAllocCommon.h"
|
||||
#include "RegClass.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetRegInfo.h"
|
||||
#include "Support/SetOperations.h"
|
||||
|
||||
unsigned LiveRange::getRegClassID() const { return getRegClass()->getID(); }
|
||||
|
||||
LiveRangeInfo::LiveRangeInfo(const Function *F, const TargetMachine &tm,
|
||||
std::vector<RegClass *> &RCL)
|
||||
: Meth(F), TM(tm), RegClassList(RCL), MRI(tm.getRegInfo()) { }
|
||||
|
||||
|
||||
LiveRangeInfo::~LiveRangeInfo() {
|
||||
for (LiveRangeMapType::iterator MI = LiveRangeMap.begin();
|
||||
MI != LiveRangeMap.end(); ++MI) {
|
||||
|
||||
if (MI->first && MI->second) {
|
||||
LiveRange *LR = MI->second;
|
||||
|
||||
// we need to be careful in deleting LiveRanges in LiveRangeMap
|
||||
// since two/more Values in the live range map can point to the same
|
||||
// live range. We have to make the other entries NULL when we delete
|
||||
// a live range.
|
||||
|
||||
for (LiveRange::iterator LI = LR->begin(); LI != LR->end(); ++LI)
|
||||
LiveRangeMap[*LI] = 0;
|
||||
|
||||
delete LR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// union two live ranges into one. The 2nd LR is deleted. Used for coalescing.
|
||||
// Note: the caller must make sure that L1 and L2 are distinct and both
|
||||
// LRs don't have suggested colors
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void LiveRangeInfo::unionAndUpdateLRs(LiveRange *L1, LiveRange *L2) {
|
||||
assert(L1 != L2 && (!L1->hasSuggestedColor() || !L2->hasSuggestedColor()));
|
||||
assert(! (L1->hasColor() && L2->hasColor()) ||
|
||||
L1->getColor() == L2->getColor());
|
||||
|
||||
set_union(*L1, *L2); // add elements of L2 to L1
|
||||
|
||||
for(ValueSet::iterator L2It = L2->begin(); L2It != L2->end(); ++L2It) {
|
||||
//assert(( L1->getTypeID() == L2->getTypeID()) && "Merge:Different types");
|
||||
|
||||
L1->insert(*L2It); // add the var in L2 to L1
|
||||
LiveRangeMap[*L2It] = L1; // now the elements in L2 should map
|
||||
//to L1
|
||||
}
|
||||
|
||||
// set call interference for L1 from L2
|
||||
if (L2->isCallInterference())
|
||||
L1->setCallInterference();
|
||||
|
||||
// add the spill costs
|
||||
L1->addSpillCost(L2->getSpillCost());
|
||||
|
||||
// If L2 has a color, give L1 that color. Note that L1 may have had the same
|
||||
// color or none, but would not have a different color as asserted above.
|
||||
if (L2->hasColor())
|
||||
L1->setColor(L2->getColor());
|
||||
|
||||
// Similarly, if LROfUse(L2) has a suggested color, the new range
|
||||
// must have the same color.
|
||||
if (L2->hasSuggestedColor())
|
||||
L1->setSuggestedColor(L2->getSuggestedColor());
|
||||
|
||||
delete L2; // delete L2 as it is no longer needed
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Method for creating a single live range for a definition.
|
||||
// The definition must be represented by a virtual register (a Value).
|
||||
// Note: this function does *not* check that no live range exists for def.
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
LiveRange*
|
||||
LiveRangeInfo::createNewLiveRange(const Value* Def, bool isCC /* = false*/)
|
||||
{
|
||||
LiveRange* DefRange = new LiveRange(); // Create a new live range,
|
||||
DefRange->insert(Def); // add Def to it,
|
||||
LiveRangeMap[Def] = DefRange; // and update the map.
|
||||
|
||||
// set the register class of the new live range
|
||||
DefRange->setRegClass(RegClassList[MRI.getRegClassIDOfType(Def->getType(),
|
||||
isCC)]);
|
||||
|
||||
if (DEBUG_RA >= RA_DEBUG_LiveRanges) {
|
||||
std::cerr << " Creating a LR for def ";
|
||||
if (isCC) std::cerr << " (CC Register!)";
|
||||
std::cerr << " : " << RAV(Def) << "\n";
|
||||
}
|
||||
return DefRange;
|
||||
}
|
||||
|
||||
|
||||
LiveRange*
|
||||
LiveRangeInfo::createOrAddToLiveRange(const Value* Def, bool isCC /* = false*/)
|
||||
{
|
||||
LiveRange *DefRange = LiveRangeMap[Def];
|
||||
|
||||
// check if the LR is already there (because of multiple defs)
|
||||
if (!DefRange) {
|
||||
DefRange = createNewLiveRange(Def, isCC);
|
||||
} else { // live range already exists
|
||||
DefRange->insert(Def); // add the operand to the range
|
||||
LiveRangeMap[Def] = DefRange; // make operand point to merged set
|
||||
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << " Added to existing LR for def: " << RAV(Def) << "\n";
|
||||
}
|
||||
return DefRange;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Method for constructing all live ranges in a function. It creates live
|
||||
// ranges for all values defined in the instruction stream. Also, it
|
||||
// creates live ranges for all incoming arguments of the function.
|
||||
//---------------------------------------------------------------------------
|
||||
void LiveRangeInfo::constructLiveRanges() {
|
||||
|
||||
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << "Constructing Live Ranges ...\n";
|
||||
|
||||
// first find the live ranges for all incoming args of the function since
|
||||
// those LRs start from the start of the function
|
||||
for (Function::const_aiterator AI = Meth->abegin(); AI != Meth->aend(); ++AI)
|
||||
createNewLiveRange(AI, /*isCC*/ false);
|
||||
|
||||
// Now suggest hardware registers for these function args
|
||||
MRI.suggestRegs4MethodArgs(Meth, *this);
|
||||
|
||||
// Now create LRs for machine instructions. A new LR will be created
|
||||
// only for defs in the machine instr since, we assume that all Values are
|
||||
// defined before they are used. However, there can be multiple defs for
|
||||
// the same Value in machine instructions.
|
||||
//
|
||||
// Also, find CALL and RETURN instructions, which need extra work.
|
||||
//
|
||||
MachineFunction &MF = MachineFunction::get(Meth);
|
||||
for (MachineFunction::iterator BBI = MF.begin(); BBI != MF.end(); ++BBI) {
|
||||
MachineBasicBlock &MBB = *BBI;
|
||||
|
||||
// iterate over all the machine instructions in BB
|
||||
for(MachineBasicBlock::iterator MInstIterator = MBB.begin();
|
||||
MInstIterator != MBB.end(); ++MInstIterator) {
|
||||
MachineInstr *MInst = *MInstIterator;
|
||||
|
||||
// If the machine instruction is a call/return instruction, add it to
|
||||
// CallRetInstrList for processing its args, ret value, and ret addr.
|
||||
//
|
||||
if(TM.getInstrInfo().isReturn(MInst->getOpCode()) ||
|
||||
TM.getInstrInfo().isCall(MInst->getOpCode()))
|
||||
CallRetInstrList.push_back(MInst);
|
||||
|
||||
// iterate over explicit MI operands and create a new LR
|
||||
// for each operand that is defined by the instruction
|
||||
for (MachineInstr::val_op_iterator OpI = MInst->begin(),
|
||||
OpE = MInst->end(); OpI != OpE; ++OpI)
|
||||
if (OpI.isDefOnly() || OpI.isDefAndUse()) {
|
||||
const Value *Def = *OpI;
|
||||
bool isCC = (OpI.getMachineOperand().getType()
|
||||
== MachineOperand::MO_CCRegister);
|
||||
LiveRange* LR = createOrAddToLiveRange(Def, isCC);
|
||||
|
||||
// If the operand has a pre-assigned register,
|
||||
// set it directly in the LiveRange
|
||||
if (OpI.getMachineOperand().hasAllocatedReg()) {
|
||||
unsigned getClassId;
|
||||
LR->setColor(MRI.getClassRegNum(
|
||||
OpI.getMachineOperand().getAllocatedRegNum(),
|
||||
getClassId));
|
||||
}
|
||||
}
|
||||
|
||||
// iterate over implicit MI operands and create a new LR
|
||||
// for each operand that is defined by the instruction
|
||||
for (unsigned i = 0; i < MInst->getNumImplicitRefs(); ++i)
|
||||
if (MInst->getImplicitOp(i).opIsDefOnly() ||
|
||||
MInst->getImplicitOp(i).opIsDefAndUse()) {
|
||||
const Value *Def = MInst->getImplicitRef(i);
|
||||
LiveRange* LR = createOrAddToLiveRange(Def, /*isCC*/ false);
|
||||
|
||||
// If the implicit operand has a pre-assigned register,
|
||||
// set it directly in the LiveRange
|
||||
if (MInst->getImplicitOp(i).hasAllocatedReg()) {
|
||||
unsigned getClassId;
|
||||
LR->setColor(MRI.getClassRegNum(
|
||||
MInst->getImplicitOp(i).getAllocatedRegNum(),
|
||||
getClassId));
|
||||
}
|
||||
}
|
||||
|
||||
} // for all machine instructions in the BB
|
||||
} // for all BBs in function
|
||||
|
||||
// Now we have to suggest clors for call and return arg live ranges.
|
||||
// Also, if there are implicit defs (e.g., retun value of a call inst)
|
||||
// they must be added to the live range list
|
||||
//
|
||||
suggestRegs4CallRets();
|
||||
|
||||
if( DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << "Initial Live Ranges constructed!\n";
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// If some live ranges must be colored with specific hardware registers
|
||||
// (e.g., for outgoing call args), suggesting of colors for such live
|
||||
// ranges is done using target specific function. Those functions are called
|
||||
// from this function. The target specific methods must:
|
||||
// 1) suggest colors for call and return args.
|
||||
// 2) create new LRs for implicit defs in machine instructions
|
||||
//---------------------------------------------------------------------------
|
||||
void LiveRangeInfo::suggestRegs4CallRets() {
|
||||
std::vector<MachineInstr*>::iterator It = CallRetInstrList.begin();
|
||||
for( ; It != CallRetInstrList.end(); ++It) {
|
||||
MachineInstr *MInst = *It;
|
||||
MachineOpCode OpCode = MInst->getOpCode();
|
||||
|
||||
if ((TM.getInstrInfo()).isReturn(OpCode))
|
||||
MRI.suggestReg4RetValue(MInst, *this);
|
||||
else if ((TM.getInstrInfo()).isCall(OpCode))
|
||||
MRI.suggestRegs4CallArgs(MInst, *this);
|
||||
else
|
||||
assert( 0 && "Non call/ret instr in CallRetInstrList" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// The following method coalesces live ranges when possible. This method
|
||||
// must be called after the interference graph has been constructed.
|
||||
|
||||
|
||||
/* Algorithm:
|
||||
for each BB in function
|
||||
for each machine instruction (inst)
|
||||
for each definition (def) in inst
|
||||
for each operand (op) of inst that is a use
|
||||
if the def and op are of the same register type
|
||||
if the def and op do not interfere //i.e., not simultaneously live
|
||||
if (degree(LR of def) + degree(LR of op)) <= # avail regs
|
||||
if both LRs do not have suggested colors
|
||||
merge2IGNodes(def, op) // i.e., merge 2 LRs
|
||||
|
||||
*/
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Checks if live range LR interferes with any node assigned or suggested to
|
||||
// be assigned the specified color
|
||||
//
|
||||
inline bool InterferesWithColor(const LiveRange& LR, unsigned color) {
|
||||
IGNode* lrNode = LR.getUserIGNode();
|
||||
for (unsigned n=0, NN = lrNode->getNumOfNeighbors(); n < NN; n++) {
|
||||
LiveRange *neighLR = lrNode->getAdjIGNode(n)->getParentLR();
|
||||
if (neighLR->hasColor() && neighLR->getColor() == color)
|
||||
return true;
|
||||
if (neighLR->hasSuggestedColor() && neighLR->getSuggestedColor() == color)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cannot coalesce if any of the following is true:
|
||||
// (1) Both LRs have suggested colors (should be "different suggested colors"?)
|
||||
// (2) Both LR1 and LR2 have colors and the colors are different
|
||||
// (but if the colors are the same, it is definitely safe to coalesce)
|
||||
// (3) LR1 has color and LR2 interferes with any LR that has the same color
|
||||
// (4) LR2 has color and LR1 interferes with any LR that has the same color
|
||||
//
|
||||
inline bool InterfsPreventCoalescing(const LiveRange& LROfDef,
|
||||
const LiveRange& LROfUse) {
|
||||
// (4) if they have different suggested colors, cannot coalesce
|
||||
if (LROfDef.hasSuggestedColor() && LROfUse.hasSuggestedColor())
|
||||
return true;
|
||||
|
||||
// if neither has a color, nothing more to do.
|
||||
if (! LROfDef.hasColor() && ! LROfUse.hasColor())
|
||||
return false;
|
||||
|
||||
// (2, 3) if L1 has color...
|
||||
if (LROfDef.hasColor()) {
|
||||
if (LROfUse.hasColor())
|
||||
return (LROfUse.getColor() != LROfDef.getColor());
|
||||
return InterferesWithColor(LROfUse, LROfDef.getColor());
|
||||
}
|
||||
|
||||
// (4) else only LROfUse has a color: check if that could interfere
|
||||
return InterferesWithColor(LROfDef, LROfUse.getColor());
|
||||
}
|
||||
|
||||
|
||||
void LiveRangeInfo::coalesceLRs()
|
||||
{
|
||||
if(DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << "\nCoalescing LRs ...\n";
|
||||
|
||||
MachineFunction &MF = MachineFunction::get(Meth);
|
||||
for (MachineFunction::iterator BBI = MF.begin(); BBI != MF.end(); ++BBI) {
|
||||
MachineBasicBlock &MBB = *BBI;
|
||||
|
||||
// iterate over all the machine instructions in BB
|
||||
for(MachineBasicBlock::iterator MII = MBB.begin(); MII != MBB.end(); ++MII){
|
||||
const MachineInstr *MI = *MII;
|
||||
|
||||
if( DEBUG_RA >= RA_DEBUG_LiveRanges) {
|
||||
std::cerr << " *Iterating over machine instr ";
|
||||
MI->dump();
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
// iterate over MI operands to find defs
|
||||
for(MachineInstr::const_val_op_iterator DefI = MI->begin(),
|
||||
DefE = MI->end(); DefI != DefE; ++DefI) {
|
||||
if (DefI.isDefOnly() || DefI.isDefAndUse()) { // this operand is modified
|
||||
LiveRange *LROfDef = getLiveRangeForValue( *DefI );
|
||||
RegClass *RCOfDef = LROfDef->getRegClass();
|
||||
|
||||
MachineInstr::const_val_op_iterator UseI = MI->begin(),
|
||||
UseE = MI->end();
|
||||
for( ; UseI != UseE; ++UseI) { // for all uses
|
||||
LiveRange *LROfUse = getLiveRangeForValue( *UseI );
|
||||
if (!LROfUse) { // if LR of use is not found
|
||||
//don't warn about labels
|
||||
if (!isa<BasicBlock>(*UseI) && DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << " !! Warning: No LR for use " << RAV(*UseI)<< "\n";
|
||||
continue; // ignore and continue
|
||||
}
|
||||
|
||||
if (LROfUse == LROfDef) // nothing to merge if they are same
|
||||
continue;
|
||||
|
||||
if (MRI.getRegTypeForLR(LROfDef) ==
|
||||
MRI.getRegTypeForLR(LROfUse)) {
|
||||
// If the two RegTypes are the same
|
||||
if (!RCOfDef->getInterference(LROfDef, LROfUse) ) {
|
||||
|
||||
unsigned CombinedDegree =
|
||||
LROfDef->getUserIGNode()->getNumOfNeighbors() +
|
||||
LROfUse->getUserIGNode()->getNumOfNeighbors();
|
||||
|
||||
if (CombinedDegree > RCOfDef->getNumOfAvailRegs()) {
|
||||
// get more precise estimate of combined degree
|
||||
CombinedDegree = LROfDef->getUserIGNode()->
|
||||
getCombinedDegree(LROfUse->getUserIGNode());
|
||||
}
|
||||
|
||||
if (CombinedDegree <= RCOfDef->getNumOfAvailRegs()) {
|
||||
// if both LRs do not have different pre-assigned colors
|
||||
// and both LRs do not have suggested colors
|
||||
if (! InterfsPreventCoalescing(*LROfDef, *LROfUse)) {
|
||||
RCOfDef->mergeIGNodesOfLRs(LROfDef, LROfUse);
|
||||
unionAndUpdateLRs(LROfDef, LROfUse);
|
||||
}
|
||||
|
||||
} // if combined degree is less than # of regs
|
||||
} // if def and use do not interfere
|
||||
}// if reg classes are the same
|
||||
} // for all uses
|
||||
} // if def
|
||||
} // for all defs
|
||||
} // for all machine instructions
|
||||
} // for all BBs
|
||||
|
||||
if (DEBUG_RA >= RA_DEBUG_LiveRanges)
|
||||
std::cerr << "\nCoalescing Done!\n";
|
||||
}
|
||||
|
||||
/*--------------------------- Debug code for printing ---------------*/
|
||||
|
||||
|
||||
void LiveRangeInfo::printLiveRanges() {
|
||||
LiveRangeMapType::iterator HMI = LiveRangeMap.begin(); // hash map iterator
|
||||
std::cerr << "\nPrinting Live Ranges from Hash Map:\n";
|
||||
for( ; HMI != LiveRangeMap.end(); ++HMI) {
|
||||
if (HMI->first && HMI->second) {
|
||||
std::cerr << " Value* " << RAV(HMI->first) << "\t: ";
|
||||
if (IGNode* igNode = HMI->second->getUserIGNode())
|
||||
std::cerr << "LR# " << igNode->getIndex();
|
||||
else
|
||||
std::cerr << "LR# " << "<no-IGNode>";
|
||||
std::cerr << "\t:Values = "; printSet(*HMI->second); std::cerr << "\n";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
//===-- LiveRangeInfo.h - Track all LiveRanges for a Function ----*- C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the class LiveRangeInfo which constructs and keeps
|
||||
// the LiveRangeMap which contains all the live ranges used in a method.
|
||||
//
|
||||
// Assumptions:
|
||||
//
|
||||
// All variables (llvm Values) are defined before they are used. However, a
|
||||
// constant may not be defined in the machine instruction stream if it can be
|
||||
// used as an immediate value within a machine instruction. However, register
|
||||
// allocation does not have to worry about immediate constants since they
|
||||
// do not require registers.
|
||||
//
|
||||
// Since an llvm Value has a list of uses associated, it is sufficient to
|
||||
// record only the defs in a Live Range.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LIVERANGEINFO_H
|
||||
#define LIVERANGEINFO_H
|
||||
|
||||
#include "llvm/CodeGen/ValueSet.h"
|
||||
#include "Support/hash_map"
|
||||
|
||||
class LiveRange;
|
||||
class MachineInstr;
|
||||
class RegClass;
|
||||
class TargetRegInfo;
|
||||
class TargetMachine;
|
||||
class Value;
|
||||
class Function;
|
||||
class Instruction;
|
||||
|
||||
typedef hash_map<const Value*, LiveRange*> LiveRangeMapType;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Class LiveRangeInfo
|
||||
//
|
||||
// Constructs and keeps the LiveRangeMap which contains all the live
|
||||
// ranges used in a method. Also contain methods to coalesce live ranges.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class LiveRangeInfo {
|
||||
const Function *const Meth; // Func for which live range info is held
|
||||
LiveRangeMapType LiveRangeMap; // A map from Value * to LiveRange * to
|
||||
// record all live ranges in a method
|
||||
// created by constructLiveRanges
|
||||
|
||||
const TargetMachine& TM; // target machine description
|
||||
|
||||
std::vector<RegClass *> & RegClassList;// vector containing register classess
|
||||
|
||||
const TargetRegInfo& MRI; // machine reg info
|
||||
|
||||
std::vector<MachineInstr*> CallRetInstrList; // a list of all call/ret instrs
|
||||
|
||||
|
||||
//------------ Private methods (see LiveRangeInfo.cpp for description)-------
|
||||
|
||||
LiveRange* createNewLiveRange (const Value* Def,
|
||||
bool isCC = false);
|
||||
|
||||
LiveRange* createOrAddToLiveRange (const Value* Def,
|
||||
bool isCC = false);
|
||||
|
||||
void unionAndUpdateLRs (LiveRange *L1,
|
||||
LiveRange *L2);
|
||||
|
||||
void addInterference (const Instruction *Inst,
|
||||
const ValueSet *LVSet);
|
||||
|
||||
void suggestRegs4CallRets ();
|
||||
|
||||
const Function *getMethod () const { return Meth; }
|
||||
|
||||
public:
|
||||
|
||||
LiveRangeInfo(const Function *F,
|
||||
const TargetMachine& tm,
|
||||
std::vector<RegClass *> & RCList);
|
||||
|
||||
|
||||
/// Destructor to destroy all LiveRanges in the LiveRange Map
|
||||
///
|
||||
~LiveRangeInfo();
|
||||
|
||||
// Main entry point for live range construction
|
||||
//
|
||||
void constructLiveRanges();
|
||||
|
||||
/// return the common live range map for this method
|
||||
///
|
||||
inline const LiveRangeMapType *getLiveRangeMap() const
|
||||
{ return &LiveRangeMap; }
|
||||
|
||||
/// Method used to get the live range containing a Value.
|
||||
/// This may return NULL if no live range exists for a Value (eg, some consts)
|
||||
///
|
||||
inline LiveRange *getLiveRangeForValue(const Value *Val) {
|
||||
return LiveRangeMap[Val];
|
||||
}
|
||||
inline const LiveRange *getLiveRangeForValue(const Value *Val) const {
|
||||
LiveRangeMapType::const_iterator I = LiveRangeMap.find(Val);
|
||||
return I->second;
|
||||
}
|
||||
|
||||
/// Method for coalescing live ranges. Called only after interference info
|
||||
/// is calculated.
|
||||
///
|
||||
void coalesceLRs();
|
||||
|
||||
/// debugging method to print the live ranges
|
||||
///
|
||||
void printLiveRanges();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,17 +0,0 @@
|
|||
##===- lib/CodeGen/RegAlloc/Makefile -----------------------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file was developed by the LLVM research group and is distributed under
|
||||
# the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../..
|
||||
|
||||
DIRS =
|
||||
|
||||
LIBRARYNAME = regalloc
|
||||
|
||||
BUILD_ARCHIVE = 1
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
File diff suppressed because it is too large
Load Diff
|
@ -1,177 +0,0 @@
|
|||
//===-- PhyRegAlloc.h - Graph Coloring Register Allocator -------*- c++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This is the main entry point for register allocation.
|
||||
//
|
||||
// Notes:
|
||||
// * RegisterClasses: Each RegClass accepts a
|
||||
// TargetRegClass which contains machine specific info about that register
|
||||
// class. The code in the RegClass is machine independent and they use
|
||||
// access functions in the TargetRegClass object passed into it to get
|
||||
// machine specific info.
|
||||
//
|
||||
// * Machine dependent work: All parts of the register coloring algorithm
|
||||
// except coloring of an individual node are machine independent.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef PHYREGALLOC_H
|
||||
#define PHYREGALLOC_H
|
||||
|
||||
#include "LiveRangeInfo.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetRegInfo.h"
|
||||
#include <map>
|
||||
|
||||
class MachineFunction;
|
||||
class FunctionLiveVarInfo;
|
||||
class MachineInstr;
|
||||
class LoopInfo;
|
||||
class RegClass;
|
||||
class Constant;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Class AddedInstrns:
|
||||
// When register allocator inserts new instructions in to the existing
|
||||
// instruction stream, it does NOT directly modify the instruction stream.
|
||||
// Rather, it creates an object of AddedInstrns and stick it in the
|
||||
// AddedInstrMap for an existing instruction. This class contains two vectors
|
||||
// to store such instructions added before and after an existing instruction.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
struct AddedInstrns {
|
||||
std::vector<MachineInstr*> InstrnsBefore;//Insts added BEFORE an existing inst
|
||||
std::vector<MachineInstr*> InstrnsAfter; //Insts added AFTER an existing inst
|
||||
inline void clear () { InstrnsBefore.clear (); InstrnsAfter.clear (); }
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// class PhyRegAlloc:
|
||||
// Main class the register allocator. Call runOnFunction() to allocate
|
||||
// registers for a Function.
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
class PhyRegAlloc : public FunctionPass {
|
||||
std::vector<RegClass *> RegClassList; // vector of register classes
|
||||
const TargetMachine &TM; // target machine
|
||||
const Function *Fn; // name of the function we work on
|
||||
MachineFunction *MF; // descriptor for method's native code
|
||||
FunctionLiveVarInfo *LVI; // LV information for this method
|
||||
// (already computed for BBs)
|
||||
LiveRangeInfo *LRI; // LR info (will be computed)
|
||||
const TargetRegInfo &MRI; // Machine Register information
|
||||
const unsigned NumOfRegClasses; // recorded here for efficiency
|
||||
|
||||
// Map to indicate whether operands of each MachineInstr have been
|
||||
// updated according to their assigned colors. This is only used in
|
||||
// assertion checking (debug builds).
|
||||
std::map<const MachineInstr *, bool> OperandsColoredMap;
|
||||
|
||||
// AddedInstrMap - Used to store instrns added in this phase
|
||||
std::map<const MachineInstr *, AddedInstrns> AddedInstrMap;
|
||||
|
||||
// ScratchRegsUsed - Contains scratch register uses for a particular MI.
|
||||
typedef std::multimap<const MachineInstr*, int> ScratchRegsUsedTy;
|
||||
ScratchRegsUsedTy ScratchRegsUsed;
|
||||
|
||||
AddedInstrns AddedInstrAtEntry; // to store instrns added at entry
|
||||
const LoopInfo *LoopDepthCalc; // to calculate loop depths
|
||||
|
||||
std::map<const Function *, std::vector<Constant *> > FnAllocState;
|
||||
|
||||
PhyRegAlloc(const PhyRegAlloc&); // DO NOT IMPLEMENT
|
||||
void operator=(const PhyRegAlloc&); // DO NOT IMPLEMENT
|
||||
public:
|
||||
inline PhyRegAlloc (const TargetMachine &TM_) :
|
||||
TM (TM_), MRI (TM.getRegInfo ()),
|
||||
NumOfRegClasses (MRI.getNumOfRegClasses ()) { }
|
||||
virtual ~PhyRegAlloc() { }
|
||||
|
||||
/// runOnFunction - Main method called for allocating registers.
|
||||
///
|
||||
virtual bool runOnFunction (Function &F);
|
||||
|
||||
virtual bool doFinalization (Module &M);
|
||||
|
||||
virtual void getAnalysisUsage (AnalysisUsage &AU) const;
|
||||
|
||||
const char *getPassName () const {
|
||||
return "Traditional graph-coloring reg. allocator";
|
||||
}
|
||||
|
||||
inline const RegClass* getRegClassByID(unsigned id) const {
|
||||
return RegClassList[id];
|
||||
}
|
||||
inline RegClass *getRegClassByID(unsigned id) { return RegClassList[id]; }
|
||||
|
||||
private:
|
||||
void addInterference(const Value *Def, const ValueSet *LVSet,
|
||||
bool isCallInst);
|
||||
bool markAllocatedRegs(MachineInstr* MInst);
|
||||
|
||||
void addInterferencesForArgs();
|
||||
void createIGNodeListsAndIGs();
|
||||
void buildInterferenceGraphs();
|
||||
void saveState();
|
||||
void verifySavedState();
|
||||
|
||||
void setCallInterferences(const MachineInstr *MI,
|
||||
const ValueSet *LVSetAft);
|
||||
|
||||
void move2DelayedInstr(const MachineInstr *OrigMI,
|
||||
const MachineInstr *DelayedMI);
|
||||
|
||||
void markUnusableSugColors();
|
||||
void allocateStackSpace4SpilledLRs();
|
||||
|
||||
void insertCode4SpilledLR(const LiveRange *LR,
|
||||
MachineBasicBlock::iterator& MII,
|
||||
MachineBasicBlock &MBB, unsigned OpNum);
|
||||
|
||||
/// Method for inserting caller saving code. The caller must save all the
|
||||
/// volatile registers live across a call.
|
||||
///
|
||||
void insertCallerSavingCode(std::vector<MachineInstr*>& instrnsBefore,
|
||||
std::vector<MachineInstr*>& instrnsAfter,
|
||||
MachineInstr *CallMI,
|
||||
const BasicBlock *BB);
|
||||
|
||||
void colorIncomingArgs();
|
||||
void colorCallRetArgs();
|
||||
void updateMachineCode();
|
||||
void updateInstruction(MachineBasicBlock::iterator& MII,
|
||||
MachineBasicBlock &MBB);
|
||||
|
||||
int getUsableUniRegAtMI(int RegType, const ValueSet *LVSetBef,
|
||||
MachineInstr *MI,
|
||||
std::vector<MachineInstr*>& MIBef,
|
||||
std::vector<MachineInstr*>& MIAft);
|
||||
|
||||
/// Callback method used to find unused registers.
|
||||
/// LVSetBef is the live variable set to search for an unused register.
|
||||
/// If it is not specified, the LV set before the current MI is used.
|
||||
/// This is sufficient as long as no new copy instructions are generated
|
||||
/// to copy the free register to memory.
|
||||
///
|
||||
int getUnusedUniRegAtMI(RegClass *RC, int RegType,
|
||||
const MachineInstr *MI,
|
||||
const ValueSet *LVSetBef = 0);
|
||||
|
||||
void setRelRegsUsedByThisInst(RegClass *RC, int RegType,
|
||||
const MachineInstr *MI);
|
||||
|
||||
int getUniRegNotUsedByThisInst(RegClass *RC, int RegType,
|
||||
const MachineInstr *MI);
|
||||
|
||||
void addInterf4PseudoInstr(const MachineInstr *MI);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,28 +0,0 @@
|
|||
//===-- RegAllocCommon.h --------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Shared declarations for register allocation.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef REGALLOCCOMMON_H
|
||||
#define REGALLOCCOMMON_H
|
||||
|
||||
enum RegAllocDebugLevel_t {
|
||||
RA_DEBUG_None = 0,
|
||||
RA_DEBUG_Results = 1,
|
||||
RA_DEBUG_Coloring = 2,
|
||||
RA_DEBUG_Interference = 3,
|
||||
RA_DEBUG_LiveRanges = 4,
|
||||
RA_DEBUG_Verbose = 5
|
||||
};
|
||||
|
||||
extern RegAllocDebugLevel_t DEBUG_RA;
|
||||
|
||||
#endif
|
|
@ -1,248 +0,0 @@
|
|||
//===-- RegClass.cpp -----------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// class RegClass for coloring-based register allocation for LLVM.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "IGNode.h"
|
||||
#include "RegAllocCommon.h"
|
||||
#include "RegClass.h"
|
||||
#include "llvm/Target/TargetRegInfo.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// This constructor inits IG. The actual matrix is created by a call to
|
||||
// createInterferenceGraph() above.
|
||||
//----------------------------------------------------------------------------
|
||||
RegClass::RegClass(const Function *M,
|
||||
const TargetRegInfo *_MRI_,
|
||||
const TargetRegClassInfo *_MRC_)
|
||||
: Meth(M), MRI(_MRI_), MRC(_MRC_),
|
||||
RegClassID( _MRC_->getRegClassID() ),
|
||||
IG(this), IGNodeStack() {
|
||||
if (DEBUG_RA >= RA_DEBUG_Interference)
|
||||
std::cerr << "Created Reg Class: " << RegClassID << "\n";
|
||||
|
||||
IsColorUsedArr.resize(MRC->getNumOfAllRegs());
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Main entry point for coloring a register class.
|
||||
//----------------------------------------------------------------------------
|
||||
void RegClass::colorAllRegs()
|
||||
{
|
||||
if (DEBUG_RA >= RA_DEBUG_Coloring)
|
||||
std::cerr << "Coloring IG of reg class " << RegClassID << " ...\n";
|
||||
// pre-color IGNodes
|
||||
pushAllIGNodes(); // push all IG Nodes
|
||||
|
||||
unsigned int StackSize = IGNodeStack.size();
|
||||
IGNode *CurIGNode;
|
||||
// for all LRs on stack
|
||||
for (unsigned int IGN=0; IGN < StackSize; IGN++) {
|
||||
CurIGNode = IGNodeStack.top(); // pop the IGNode on top of stack
|
||||
IGNodeStack.pop();
|
||||
colorIGNode (CurIGNode); // color it
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// The method for pushing all IGNodes on to the stack.
|
||||
//----------------------------------------------------------------------------
|
||||
void RegClass::pushAllIGNodes()
|
||||
{
|
||||
bool NeedMoreSpills;
|
||||
|
||||
|
||||
IG.setCurDegreeOfIGNodes(); // calculate degree of IGNodes
|
||||
|
||||
// push non-constrained IGNodes
|
||||
bool PushedAll = pushUnconstrainedIGNodes();
|
||||
|
||||
if (DEBUG_RA >= RA_DEBUG_Coloring) {
|
||||
std::cerr << " Puhsed all-unconstrained IGNodes. ";
|
||||
if( PushedAll ) std::cerr << " No constrained nodes left.";
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
if (PushedAll) // if NO constrained nodes left
|
||||
return;
|
||||
|
||||
|
||||
// now, we have constrained nodes. So, push one of them (the one with min
|
||||
// spill cost) and try to push the others as unConstrained nodes.
|
||||
// Repeat this.
|
||||
|
||||
do {
|
||||
//get node with min spill cost
|
||||
IGNode *IGNodeSpill = getIGNodeWithMinSpillCost();
|
||||
// push that node on to stack
|
||||
IGNodeStack.push(IGNodeSpill);
|
||||
// set its OnStack flag and decrement degree of neighs
|
||||
IGNodeSpill->pushOnStack();
|
||||
// now push NON-constrained ones, if any
|
||||
NeedMoreSpills = !pushUnconstrainedIGNodes();
|
||||
if (DEBUG_RA >= RA_DEBUG_Coloring)
|
||||
std::cerr << "\nConstrained IG Node found !@!" << IGNodeSpill->getIndex();
|
||||
} while(NeedMoreSpills); // repeat until we have pushed all
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// This method goes thru all IG nodes in the IGNodeList of an IG of a
|
||||
// register class and push any unconstrained IG node left (that is not
|
||||
// already pushed)
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
bool RegClass::pushUnconstrainedIGNodes()
|
||||
{
|
||||
// # of LRs for this reg class
|
||||
unsigned int IGNodeListSize = IG.getIGNodeList().size();
|
||||
bool pushedall = true;
|
||||
|
||||
// a pass over IGNodeList
|
||||
for (unsigned i =0; i < IGNodeListSize; i++) {
|
||||
|
||||
// get IGNode i from IGNodeList
|
||||
IGNode *IGNode = IG.getIGNodeList()[i];
|
||||
|
||||
if (!IGNode ) // can be null due to merging
|
||||
continue;
|
||||
|
||||
// if already pushed on stack, continue. This can happen since this
|
||||
// method can be called repeatedly until all constrained nodes are
|
||||
// pushed
|
||||
if (IGNode->isOnStack() )
|
||||
continue;
|
||||
// if the degree of IGNode is lower
|
||||
if ((unsigned) IGNode->getCurDegree() < MRC->getNumOfAvailRegs()) {
|
||||
IGNodeStack.push( IGNode ); // push IGNode on to the stack
|
||||
IGNode->pushOnStack(); // set OnStack and dec deg of neighs
|
||||
|
||||
if (DEBUG_RA >= RA_DEBUG_Coloring) {
|
||||
std::cerr << " pushed un-constrained IGNode " << IGNode->getIndex()
|
||||
<< " on to stack\n";
|
||||
}
|
||||
}
|
||||
else pushedall = false; // we didn't push all live ranges
|
||||
|
||||
} // for
|
||||
|
||||
// returns true if we pushed all live ranges - else false
|
||||
return pushedall;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Get the IGNode with the minimum spill cost
|
||||
//----------------------------------------------------------------------------
|
||||
IGNode * RegClass::getIGNodeWithMinSpillCost() {
|
||||
unsigned int IGNodeListSize = IG.getIGNodeList().size();
|
||||
double MinSpillCost = 0;
|
||||
IGNode *MinCostIGNode = NULL;
|
||||
bool isFirstNode = true;
|
||||
|
||||
// pass over IGNodeList to find the IGNode with minimum spill cost
|
||||
// among all IGNodes that are not yet pushed on to the stack
|
||||
for (unsigned int i =0; i < IGNodeListSize; i++) {
|
||||
IGNode *IGNode = IG.getIGNodeList()[i];
|
||||
|
||||
if (!IGNode) // can be null due to merging
|
||||
continue;
|
||||
|
||||
if (!IGNode->isOnStack()) {
|
||||
double SpillCost = (double) IGNode->getParentLR()->getSpillCost() /
|
||||
(double) (IGNode->getCurDegree() + 1);
|
||||
|
||||
if (isFirstNode) { // for the first IG node
|
||||
MinSpillCost = SpillCost;
|
||||
MinCostIGNode = IGNode;
|
||||
isFirstNode = false;
|
||||
} else if (MinSpillCost > SpillCost) {
|
||||
MinSpillCost = SpillCost;
|
||||
MinCostIGNode = IGNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (MinCostIGNode && "No IGNode to spill");
|
||||
return MinCostIGNode;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Color the IGNode using the machine specific code.
|
||||
//----------------------------------------------------------------------------
|
||||
void RegClass::colorIGNode(IGNode *const Node) {
|
||||
if (! Node->hasColor()) { // not colored as an arg etc.
|
||||
|
||||
// init all elements of to IsColorUsedAr false;
|
||||
clearColorsUsed();
|
||||
|
||||
// initialize all colors used by neighbors of this node to true
|
||||
LiveRange *LR = Node->getParentLR();
|
||||
unsigned NumNeighbors = Node->getNumOfNeighbors();
|
||||
for (unsigned n=0; n < NumNeighbors; n++) {
|
||||
IGNode *NeighIGNode = Node->getAdjIGNode(n);
|
||||
LiveRange *NeighLR = NeighIGNode->getParentLR();
|
||||
|
||||
// Don't use a color if it is in use by the neighbor,
|
||||
// or is suggested for use by the neighbor,
|
||||
// markColorsUsed() should be given the color and the reg type for
|
||||
// LR, not for NeighLR, because it should mark registers used based on
|
||||
// the type we are looking for, not on the regType for the neighbour.
|
||||
if (NeighLR->hasColor())
|
||||
this->markColorsUsed(NeighLR->getColor(),
|
||||
MRI->getRegTypeForLR(NeighLR),
|
||||
MRI->getRegTypeForLR(LR)); // use LR, not NeighLR
|
||||
else if (NeighLR->hasSuggestedColor() &&
|
||||
NeighLR->isSuggestedColorUsable())
|
||||
this->markColorsUsed(NeighLR->getSuggestedColor(),
|
||||
MRI->getRegTypeForLR(NeighLR),
|
||||
MRI->getRegTypeForLR(LR)); // use LR, not NeighLR
|
||||
}
|
||||
|
||||
// call the target specific code for coloring
|
||||
//
|
||||
MRC->colorIGNode(Node, IsColorUsedArr);
|
||||
} else {
|
||||
if (DEBUG_RA >= RA_DEBUG_Coloring) {
|
||||
std::cerr << " Node " << Node->getIndex();
|
||||
std::cerr << " already colored with color " << Node->getColor() << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!Node->hasColor() ) {
|
||||
if (DEBUG_RA >= RA_DEBUG_Coloring) {
|
||||
std::cerr << " Node " << Node->getIndex();
|
||||
std::cerr << " - could not find a color (needs spilling)\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RegClass::printIGNodeList() const {
|
||||
std::cerr << "IG Nodes for Register Class " << RegClassID << ":" << "\n";
|
||||
IG.printIGNodeList();
|
||||
}
|
||||
|
||||
void RegClass::printIG() {
|
||||
std::cerr << "IG for Register Class " << RegClassID << ":" << "\n";
|
||||
IG.printIG();
|
||||
}
|
||||
|
||||
|
|
@ -1,142 +0,0 @@
|
|||
//===-- RegClass.h - Machine Independent register coloring ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/* Title: RegClass.h -*- C++ -*-
|
||||
Author: Ruchira Sasanka
|
||||
Date: Aug 20, 01
|
||||
Purpose: Contains machine independent methods for register coloring.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef REGCLASS_H
|
||||
#define REGCLASS_H
|
||||
|
||||
#include "llvm/Target/TargetRegInfo.h"
|
||||
#include "InterferenceGraph.h"
|
||||
#include <stack>
|
||||
class TargetRegClassInfo;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Class RegClass
|
||||
//
|
||||
// Implements a machine independent register class.
|
||||
//
|
||||
// This is the class that contains all data structures and common algos
|
||||
// for coloring a particular register class (e.g., int class, fp class).
|
||||
// This class is hardware independent. This class accepts a hardware
|
||||
// dependent description of machine registers (TargetRegInfo class) to
|
||||
// get hardware specific info and to color an individual IG node.
|
||||
//
|
||||
// This class contains the InterferenceGraph (IG).
|
||||
// Also it contains an IGNode stack that can be used for coloring.
|
||||
// The class provides some easy access methods to the IG methods, since these
|
||||
// methods are called thru a register class.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
class RegClass {
|
||||
const Function *const Meth; // Function we are working on
|
||||
const TargetRegInfo *MRI; // Machine register information
|
||||
const TargetRegClassInfo *const MRC; // Machine reg. class for this RegClass
|
||||
const unsigned RegClassID; // my int ID
|
||||
|
||||
InterferenceGraph IG; // Interference graph - constructed by
|
||||
// buildInterferenceGraph
|
||||
std::stack<IGNode *> IGNodeStack; // the stack used for coloring
|
||||
|
||||
// IsColorUsedArr - An array used for coloring each node. This array must be
|
||||
// of size MRC->getNumOfAllRegs(). Allocated once in the constructor for
|
||||
// efficiency.
|
||||
//
|
||||
std::vector<bool> IsColorUsedArr;
|
||||
|
||||
|
||||
|
||||
//--------------------------- private methods ------------------------------
|
||||
|
||||
void pushAllIGNodes();
|
||||
|
||||
bool pushUnconstrainedIGNodes();
|
||||
|
||||
IGNode * getIGNodeWithMinSpillCost();
|
||||
|
||||
void colorIGNode(IGNode *const Node);
|
||||
|
||||
// This directly marks the colors used by a particular register number
|
||||
// within the register class. External users should use the public
|
||||
// versions of this function below.
|
||||
inline void markColorUsed(unsigned classRegNum) {
|
||||
assert(classRegNum < IsColorUsedArr.size() && "Invalid register used?");
|
||||
IsColorUsedArr[classRegNum] = true;
|
||||
}
|
||||
|
||||
inline bool isColorUsed(unsigned regNum) const {
|
||||
assert(regNum < IsColorUsedArr.size() && "Invalid register used?");
|
||||
return IsColorUsedArr[regNum];
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
RegClass(const Function *M,
|
||||
const TargetRegInfo *_MRI_,
|
||||
const TargetRegClassInfo *_MRC_);
|
||||
|
||||
inline void createInterferenceGraph() { IG.createGraph(); }
|
||||
|
||||
inline InterferenceGraph &getIG() { return IG; }
|
||||
|
||||
inline const unsigned getID() const { return RegClassID; }
|
||||
|
||||
inline const TargetRegClassInfo* getTargetRegClass() const { return MRC; }
|
||||
|
||||
// main method called for coloring regs
|
||||
//
|
||||
void colorAllRegs();
|
||||
|
||||
inline unsigned getNumOfAvailRegs() const
|
||||
{ return MRC->getNumOfAvailRegs(); }
|
||||
|
||||
|
||||
// --- following methods are provided to access the IG contained within this
|
||||
// ---- RegClass easilly.
|
||||
|
||||
inline void addLRToIG(LiveRange *const LR)
|
||||
{ IG.addLRToIG(LR); }
|
||||
|
||||
inline void setInterference(const LiveRange *const LR1,
|
||||
const LiveRange *const LR2)
|
||||
{ IG.setInterference(LR1, LR2); }
|
||||
|
||||
inline unsigned getInterference(const LiveRange *const LR1,
|
||||
const LiveRange *const LR2) const
|
||||
{ return IG.getInterference(LR1, LR2); }
|
||||
|
||||
inline void mergeIGNodesOfLRs(const LiveRange *const LR1,
|
||||
LiveRange *const LR2)
|
||||
{ IG.mergeIGNodesOfLRs(LR1, LR2); }
|
||||
|
||||
|
||||
inline void clearColorsUsed() {
|
||||
IsColorUsedArr.clear();
|
||||
IsColorUsedArr.resize(MRC->getNumOfAllRegs());
|
||||
}
|
||||
inline void markColorsUsed(unsigned ClassRegNum,
|
||||
int UserRegType,
|
||||
int RegTypeWanted) {
|
||||
MRC->markColorsUsed(ClassRegNum, UserRegType, RegTypeWanted,IsColorUsedArr);
|
||||
}
|
||||
inline int getUnusedColor(int machineRegType) const {
|
||||
return MRC->findUnusedColor(machineRegType, IsColorUsedArr);
|
||||
}
|
||||
|
||||
void printIGNodeList() const;
|
||||
void printIG();
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,600 +0,0 @@
|
|||
//===-- FloatingPoint.cpp - Floating point Reg -> Stack converter ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the pass which converts floating point instructions from
|
||||
// virtual registers into register stack instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "fp"
|
||||
#include "X86.h"
|
||||
#include "X86InstrInfo.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/LiveVariables.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "Support/Debug.h"
|
||||
#include "Support/Statistic.h"
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
namespace {
|
||||
Statistic<> NumFXCH("x86-codegen", "Number of fxch instructions inserted");
|
||||
Statistic<> NumFP ("x86-codegen", "Number of floating point instructions");
|
||||
|
||||
struct FPS : public MachineFunctionPass {
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
virtual const char *getPassName() const { return "X86 FP Stackifier"; }
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<LiveVariables>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
private:
|
||||
LiveVariables *LV; // Live variable info for current function...
|
||||
MachineBasicBlock *MBB; // Current basic block
|
||||
unsigned Stack[8]; // FP<n> Registers in each stack slot...
|
||||
unsigned RegMap[8]; // Track which stack slot contains each register
|
||||
unsigned StackTop; // The current top of the FP stack.
|
||||
|
||||
void dumpStack() const {
|
||||
std::cerr << "Stack contents:";
|
||||
for (unsigned i = 0; i != StackTop; ++i) {
|
||||
std::cerr << " FP" << Stack[i];
|
||||
assert(RegMap[Stack[i]] == i && "Stack[] doesn't match RegMap[]!");
|
||||
}
|
||||
std::cerr << "\n";
|
||||
}
|
||||
private:
|
||||
// getSlot - Return the stack slot number a particular register number is
|
||||
// in...
|
||||
unsigned getSlot(unsigned RegNo) const {
|
||||
assert(RegNo < 8 && "Regno out of range!");
|
||||
return RegMap[RegNo];
|
||||
}
|
||||
|
||||
// getStackEntry - Return the X86::FP<n> register in register ST(i)
|
||||
unsigned getStackEntry(unsigned STi) const {
|
||||
assert(STi < StackTop && "Access past stack top!");
|
||||
return Stack[StackTop-1-STi];
|
||||
}
|
||||
|
||||
// getSTReg - Return the X86::ST(i) register which contains the specified
|
||||
// FP<RegNo> register
|
||||
unsigned getSTReg(unsigned RegNo) const {
|
||||
return StackTop - 1 - getSlot(RegNo) + X86::ST0;
|
||||
}
|
||||
|
||||
// pushReg - Push the specifiex FP<n> register onto the stack
|
||||
void pushReg(unsigned Reg) {
|
||||
assert(Reg < 8 && "Register number out of range!");
|
||||
assert(StackTop < 8 && "Stack overflow!");
|
||||
Stack[StackTop] = Reg;
|
||||
RegMap[Reg] = StackTop++;
|
||||
}
|
||||
|
||||
bool isAtTop(unsigned RegNo) const { return getSlot(RegNo) == StackTop-1; }
|
||||
void moveToTop(unsigned RegNo, MachineBasicBlock::iterator &I) {
|
||||
if (!isAtTop(RegNo)) {
|
||||
unsigned Slot = getSlot(RegNo);
|
||||
unsigned STReg = getSTReg(RegNo);
|
||||
unsigned RegOnTop = getStackEntry(0);
|
||||
|
||||
// Swap the slots the regs are in
|
||||
std::swap(RegMap[RegNo], RegMap[RegOnTop]);
|
||||
|
||||
// Swap stack slot contents
|
||||
assert(RegMap[RegOnTop] < StackTop);
|
||||
std::swap(Stack[RegMap[RegOnTop]], Stack[StackTop-1]);
|
||||
|
||||
// Emit an fxch to update the runtime processors version of the state
|
||||
MachineInstr *MI = BuildMI(X86::FXCH, 1).addReg(STReg);
|
||||
I = 1+MBB->insert(I, MI);
|
||||
NumFXCH++;
|
||||
}
|
||||
}
|
||||
|
||||
void duplicateToTop(unsigned RegNo, unsigned AsReg,
|
||||
MachineBasicBlock::iterator &I) {
|
||||
unsigned STReg = getSTReg(RegNo);
|
||||
pushReg(AsReg); // New register on top of stack
|
||||
|
||||
MachineInstr *MI = BuildMI(X86::FLDrr, 1).addReg(STReg);
|
||||
I = 1+MBB->insert(I, MI);
|
||||
}
|
||||
|
||||
// popStackAfter - Pop the current value off of the top of the FP stack
|
||||
// after the specified instruction.
|
||||
void popStackAfter(MachineBasicBlock::iterator &I);
|
||||
|
||||
bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
|
||||
|
||||
void handleZeroArgFP(MachineBasicBlock::iterator &I);
|
||||
void handleOneArgFP(MachineBasicBlock::iterator &I);
|
||||
void handleTwoArgFP(MachineBasicBlock::iterator &I);
|
||||
void handleSpecialFP(MachineBasicBlock::iterator &I);
|
||||
};
|
||||
}
|
||||
|
||||
FunctionPass *createX86FloatingPointStackifierPass() { return new FPS(); }
|
||||
|
||||
/// runOnMachineFunction - Loop over all of the basic blocks, transforming FP
|
||||
/// register references into FP stack references.
|
||||
///
|
||||
bool FPS::runOnMachineFunction(MachineFunction &MF) {
|
||||
LV = &getAnalysis<LiveVariables>();
|
||||
StackTop = 0;
|
||||
|
||||
bool Changed = false;
|
||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I)
|
||||
Changed |= processBasicBlock(MF, *I);
|
||||
return Changed;
|
||||
}
|
||||
|
||||
/// processBasicBlock - Loop over all of the instructions in the basic block,
|
||||
/// transforming FP instructions into their stack form.
|
||||
///
|
||||
bool FPS::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
|
||||
const TargetInstrInfo &TII = MF.getTarget().getInstrInfo();
|
||||
bool Changed = false;
|
||||
MBB = &BB;
|
||||
|
||||
for (MachineBasicBlock::iterator I = BB.begin(); I != BB.end(); ++I) {
|
||||
MachineInstr *MI = *I;
|
||||
MachineInstr *PrevMI = I == BB.begin() ? 0 : *(I-1);
|
||||
unsigned Flags = TII.get(MI->getOpcode()).TSFlags;
|
||||
|
||||
if ((Flags & X86II::FPTypeMask) == 0) continue; // Ignore non-fp insts!
|
||||
|
||||
++NumFP; // Keep track of # of pseudo instrs
|
||||
DEBUG(std::cerr << "\nFPInst:\t";
|
||||
MI->print(std::cerr, MF.getTarget()));
|
||||
|
||||
// Get dead variables list now because the MI pointer may be deleted as part
|
||||
// of processing!
|
||||
LiveVariables::killed_iterator IB = LV->dead_begin(MI);
|
||||
LiveVariables::killed_iterator IE = LV->dead_end(MI);
|
||||
|
||||
DEBUG(const MRegisterInfo *MRI = MF.getTarget().getRegisterInfo();
|
||||
LiveVariables::killed_iterator I = LV->killed_begin(MI);
|
||||
LiveVariables::killed_iterator E = LV->killed_end(MI);
|
||||
if (I != E) {
|
||||
std::cerr << "Killed Operands:";
|
||||
for (; I != E; ++I)
|
||||
std::cerr << " %" << MRI->getName(I->second);
|
||||
std::cerr << "\n";
|
||||
});
|
||||
|
||||
switch (Flags & X86II::FPTypeMask) {
|
||||
case X86II::ZeroArgFP: handleZeroArgFP(I); break;
|
||||
case X86II::OneArgFP: handleOneArgFP(I); break;
|
||||
|
||||
case X86II::OneArgFPRW: // ST(0) = fsqrt(ST(0))
|
||||
assert(0 && "FP instr type not handled yet!");
|
||||
|
||||
case X86II::TwoArgFP: handleTwoArgFP(I); break;
|
||||
case X86II::SpecialFP: handleSpecialFP(I); break;
|
||||
default: assert(0 && "Unknown FP Type!");
|
||||
}
|
||||
|
||||
// Check to see if any of the values defined by this instruction are dead
|
||||
// after definition. If so, pop them.
|
||||
for (; IB != IE; ++IB) {
|
||||
unsigned Reg = IB->second;
|
||||
if (Reg >= X86::FP0 && Reg <= X86::FP6) {
|
||||
DEBUG(std::cerr << "Register FP#" << Reg-X86::FP0 << " is dead!\n");
|
||||
++I; // Insert fxch AFTER the instruction
|
||||
moveToTop(Reg-X86::FP0, I); // Insert fxch if necessary
|
||||
--I; // Move to fxch or old instruction
|
||||
popStackAfter(I); // Pop the top of the stack, killing value
|
||||
}
|
||||
}
|
||||
|
||||
// Print out all of the instructions expanded to if -debug
|
||||
DEBUG(if (*I == PrevMI) {
|
||||
std::cerr<< "Just deleted pseudo instruction\n";
|
||||
} else {
|
||||
MachineBasicBlock::iterator Start = I;
|
||||
// Rewind to first instruction newly inserted.
|
||||
while (Start != BB.begin() && *(Start-1) != PrevMI) --Start;
|
||||
std::cerr << "Inserted instructions:\n\t";
|
||||
(*Start)->print(std::cerr, MF.getTarget());
|
||||
while (++Start != I+1);
|
||||
}
|
||||
dumpStack();
|
||||
);
|
||||
|
||||
Changed = true;
|
||||
}
|
||||
|
||||
assert(StackTop == 0 && "Stack not empty at end of basic block?");
|
||||
return Changed;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Efficient Lookup Table Support
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
struct TableEntry {
|
||||
unsigned from;
|
||||
unsigned to;
|
||||
bool operator<(const TableEntry &TE) const { return from < TE.from; }
|
||||
bool operator<(unsigned V) const { return from < V; }
|
||||
};
|
||||
|
||||
static bool TableIsSorted(const TableEntry *Table, unsigned NumEntries) {
|
||||
for (unsigned i = 0; i != NumEntries-1; ++i)
|
||||
if (!(Table[i] < Table[i+1])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int Lookup(const TableEntry *Table, unsigned N, unsigned Opcode) {
|
||||
const TableEntry *I = std::lower_bound(Table, Table+N, Opcode);
|
||||
if (I != Table+N && I->from == Opcode)
|
||||
return I->to;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define ARRAY_SIZE(TABLE) \
|
||||
(sizeof(TABLE)/sizeof(TABLE[0]))
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define ASSERT_SORTED(TABLE)
|
||||
#else
|
||||
#define ASSERT_SORTED(TABLE) \
|
||||
{ static bool TABLE##Checked = false; \
|
||||
if (!TABLE##Checked) \
|
||||
assert(TableIsSorted(TABLE, ARRAY_SIZE(TABLE)) && \
|
||||
"All lookup tables must be sorted for efficient access!"); \
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Helper Methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// PopTable - Sorted map of instructions to their popping version. The first
|
||||
// element is an instruction, the second is the version which pops.
|
||||
//
|
||||
static const TableEntry PopTable[] = {
|
||||
{ X86::FADDrST0 , X86::FADDPrST0 },
|
||||
|
||||
{ X86::FDIVRrST0, X86::FDIVRPrST0 },
|
||||
{ X86::FDIVrST0 , X86::FDIVPrST0 },
|
||||
|
||||
{ X86::FISTr16 , X86::FISTPr16 },
|
||||
{ X86::FISTr32 , X86::FISTPr32 },
|
||||
|
||||
{ X86::FMULrST0 , X86::FMULPrST0 },
|
||||
|
||||
{ X86::FSTr32 , X86::FSTPr32 },
|
||||
{ X86::FSTr64 , X86::FSTPr64 },
|
||||
{ X86::FSTrr , X86::FSTPrr },
|
||||
|
||||
{ X86::FSUBRrST0, X86::FSUBRPrST0 },
|
||||
{ X86::FSUBrST0 , X86::FSUBPrST0 },
|
||||
|
||||
{ X86::FUCOMPr , X86::FUCOMPPr },
|
||||
{ X86::FUCOMr , X86::FUCOMPr },
|
||||
};
|
||||
|
||||
/// popStackAfter - Pop the current value off of the top of the FP stack after
|
||||
/// the specified instruction. This attempts to be sneaky and combine the pop
|
||||
/// into the instruction itself if possible. The iterator is left pointing to
|
||||
/// the last instruction, be it a new pop instruction inserted, or the old
|
||||
/// instruction if it was modified in place.
|
||||
///
|
||||
void FPS::popStackAfter(MachineBasicBlock::iterator &I) {
|
||||
ASSERT_SORTED(PopTable);
|
||||
assert(StackTop > 0 && "Cannot pop empty stack!");
|
||||
RegMap[Stack[--StackTop]] = ~0; // Update state
|
||||
|
||||
// Check to see if there is a popping version of this instruction...
|
||||
int Opcode = Lookup(PopTable, ARRAY_SIZE(PopTable), (*I)->getOpcode());
|
||||
if (Opcode != -1) {
|
||||
(*I)->setOpcode(Opcode);
|
||||
if (Opcode == X86::FUCOMPPr)
|
||||
(*I)->RemoveOperand(0);
|
||||
|
||||
} else { // Insert an explicit pop
|
||||
MachineInstr *MI = BuildMI(X86::FSTPrr, 1).addReg(X86::ST0);
|
||||
I = MBB->insert(I+1, MI);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned getFPReg(const MachineOperand &MO) {
|
||||
assert(MO.isPhysicalRegister() && "Expected an FP register!");
|
||||
unsigned Reg = MO.getReg();
|
||||
assert(Reg >= X86::FP0 && Reg <= X86::FP6 && "Expected FP register!");
|
||||
return Reg - X86::FP0;
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction transformation implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// handleZeroArgFP - ST(0) = fld0 ST(0) = flds <mem>
|
||||
//
|
||||
void FPS::handleZeroArgFP(MachineBasicBlock::iterator &I) {
|
||||
MachineInstr *MI = *I;
|
||||
unsigned DestReg = getFPReg(MI->getOperand(0));
|
||||
MI->RemoveOperand(0); // Remove the explicit ST(0) operand
|
||||
|
||||
// Result gets pushed on the stack...
|
||||
pushReg(DestReg);
|
||||
}
|
||||
|
||||
/// handleOneArgFP - fst ST(0), <mem>
|
||||
//
|
||||
void FPS::handleOneArgFP(MachineBasicBlock::iterator &I) {
|
||||
MachineInstr *MI = *I;
|
||||
assert(MI->getNumOperands() == 5 && "Can only handle fst* instructions!");
|
||||
|
||||
unsigned Reg = getFPReg(MI->getOperand(4));
|
||||
bool KillsSrc = false;
|
||||
for (LiveVariables::killed_iterator KI = LV->killed_begin(MI),
|
||||
E = LV->killed_end(MI); KI != E; ++KI)
|
||||
KillsSrc |= KI->second == X86::FP0+Reg;
|
||||
|
||||
// FSTPr80 and FISTPr64 are strange because there are no non-popping versions.
|
||||
// If we have one _and_ we don't want to pop the operand, duplicate the value
|
||||
// on the stack instead of moving it. This ensure that popping the value is
|
||||
// always ok.
|
||||
//
|
||||
if ((MI->getOpcode() == X86::FSTPr80 ||
|
||||
MI->getOpcode() == X86::FISTPr64) && !KillsSrc) {
|
||||
duplicateToTop(Reg, 7 /*temp register*/, I);
|
||||
} else {
|
||||
moveToTop(Reg, I); // Move to the top of the stack...
|
||||
}
|
||||
MI->RemoveOperand(4); // Remove explicit ST(0) operand
|
||||
|
||||
if (MI->getOpcode() == X86::FSTPr80 || MI->getOpcode() == X86::FISTPr64) {
|
||||
assert(StackTop > 0 && "Stack empty??");
|
||||
--StackTop;
|
||||
} else if (KillsSrc) { // Last use of operand?
|
||||
popStackAfter(I);
|
||||
}
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Define tables of various ways to map pseudo instructions
|
||||
//
|
||||
|
||||
// ForwardST0Table - Map: A = B op C into: ST(0) = ST(0) op ST(i)
|
||||
static const TableEntry ForwardST0Table[] = {
|
||||
{ X86::FpADD, X86::FADDST0r },
|
||||
{ X86::FpDIV, X86::FDIVST0r },
|
||||
{ X86::FpMUL, X86::FMULST0r },
|
||||
{ X86::FpSUB, X86::FSUBST0r },
|
||||
{ X86::FpUCOM, X86::FUCOMr },
|
||||
};
|
||||
|
||||
// ReverseST0Table - Map: A = B op C into: ST(0) = ST(i) op ST(0)
|
||||
static const TableEntry ReverseST0Table[] = {
|
||||
{ X86::FpADD, X86::FADDST0r }, // commutative
|
||||
{ X86::FpDIV, X86::FDIVRST0r },
|
||||
{ X86::FpMUL, X86::FMULST0r }, // commutative
|
||||
{ X86::FpSUB, X86::FSUBRST0r },
|
||||
{ X86::FpUCOM, ~0 },
|
||||
};
|
||||
|
||||
// ForwardSTiTable - Map: A = B op C into: ST(i) = ST(0) op ST(i)
|
||||
static const TableEntry ForwardSTiTable[] = {
|
||||
{ X86::FpADD, X86::FADDrST0 }, // commutative
|
||||
{ X86::FpDIV, X86::FDIVRrST0 },
|
||||
{ X86::FpMUL, X86::FMULrST0 }, // commutative
|
||||
{ X86::FpSUB, X86::FSUBRrST0 },
|
||||
{ X86::FpUCOM, X86::FUCOMr },
|
||||
};
|
||||
|
||||
// ReverseSTiTable - Map: A = B op C into: ST(i) = ST(i) op ST(0)
|
||||
static const TableEntry ReverseSTiTable[] = {
|
||||
{ X86::FpADD, X86::FADDrST0 },
|
||||
{ X86::FpDIV, X86::FDIVrST0 },
|
||||
{ X86::FpMUL, X86::FMULrST0 },
|
||||
{ X86::FpSUB, X86::FSUBrST0 },
|
||||
{ X86::FpUCOM, ~0 },
|
||||
};
|
||||
|
||||
|
||||
/// handleTwoArgFP - Handle instructions like FADD and friends which are virtual
|
||||
/// instructions which need to be simplified and possibly transformed.
|
||||
///
|
||||
/// Result: ST(0) = fsub ST(0), ST(i)
|
||||
/// ST(i) = fsub ST(0), ST(i)
|
||||
/// ST(0) = fsubr ST(0), ST(i)
|
||||
/// ST(i) = fsubr ST(0), ST(i)
|
||||
///
|
||||
/// In addition to three address instructions, this also handles the FpUCOM
|
||||
/// instruction which only has two operands, but no destination. This
|
||||
/// instruction is also annoying because there is no "reverse" form of it
|
||||
/// available.
|
||||
///
|
||||
void FPS::handleTwoArgFP(MachineBasicBlock::iterator &I) {
|
||||
ASSERT_SORTED(ForwardST0Table); ASSERT_SORTED(ReverseST0Table);
|
||||
ASSERT_SORTED(ForwardSTiTable); ASSERT_SORTED(ReverseSTiTable);
|
||||
MachineInstr *MI = *I;
|
||||
|
||||
unsigned NumOperands = MI->getNumOperands();
|
||||
assert(NumOperands == 3 ||
|
||||
(NumOperands == 2 && MI->getOpcode() == X86::FpUCOM) &&
|
||||
"Illegal TwoArgFP instruction!");
|
||||
unsigned Dest = getFPReg(MI->getOperand(0));
|
||||
unsigned Op0 = getFPReg(MI->getOperand(NumOperands-2));
|
||||
unsigned Op1 = getFPReg(MI->getOperand(NumOperands-1));
|
||||
bool KillsOp0 = false, KillsOp1 = false;
|
||||
|
||||
for (LiveVariables::killed_iterator KI = LV->killed_begin(MI),
|
||||
E = LV->killed_end(MI); KI != E; ++KI) {
|
||||
KillsOp0 |= (KI->second == X86::FP0+Op0);
|
||||
KillsOp1 |= (KI->second == X86::FP0+Op1);
|
||||
}
|
||||
|
||||
// If this is an FpUCOM instruction, we must make sure the first operand is on
|
||||
// the top of stack, the other one can be anywhere...
|
||||
if (MI->getOpcode() == X86::FpUCOM)
|
||||
moveToTop(Op0, I);
|
||||
|
||||
unsigned TOS = getStackEntry(0);
|
||||
|
||||
// One of our operands must be on the top of the stack. If neither is yet, we
|
||||
// need to move one.
|
||||
if (Op0 != TOS && Op1 != TOS) { // No operand at TOS?
|
||||
// We can choose to move either operand to the top of the stack. If one of
|
||||
// the operands is killed by this instruction, we want that one so that we
|
||||
// can update right on top of the old version.
|
||||
if (KillsOp0) {
|
||||
moveToTop(Op0, I); // Move dead operand to TOS.
|
||||
TOS = Op0;
|
||||
} else if (KillsOp1) {
|
||||
moveToTop(Op1, I);
|
||||
TOS = Op1;
|
||||
} else {
|
||||
// All of the operands are live after this instruction executes, so we
|
||||
// cannot update on top of any operand. Because of this, we must
|
||||
// duplicate one of the stack elements to the top. It doesn't matter
|
||||
// which one we pick.
|
||||
//
|
||||
duplicateToTop(Op0, Dest, I);
|
||||
Op0 = TOS = Dest;
|
||||
KillsOp0 = true;
|
||||
}
|
||||
} else if (!KillsOp0 && !KillsOp1 && MI->getOpcode() != X86::FpUCOM) {
|
||||
// If we DO have one of our operands at the top of the stack, but we don't
|
||||
// have a dead operand, we must duplicate one of the operands to a new slot
|
||||
// on the stack.
|
||||
duplicateToTop(Op0, Dest, I);
|
||||
Op0 = TOS = Dest;
|
||||
KillsOp0 = true;
|
||||
}
|
||||
|
||||
// Now we know that one of our operands is on the top of the stack, and at
|
||||
// least one of our operands is killed by this instruction.
|
||||
assert((TOS == Op0 || TOS == Op1) &&
|
||||
(KillsOp0 || KillsOp1 || MI->getOpcode() == X86::FpUCOM) &&
|
||||
"Stack conditions not set up right!");
|
||||
|
||||
// We decide which form to use based on what is on the top of the stack, and
|
||||
// which operand is killed by this instruction.
|
||||
const TableEntry *InstTable;
|
||||
bool isForward = TOS == Op0;
|
||||
bool updateST0 = (TOS == Op0 && !KillsOp1) || (TOS == Op1 && !KillsOp0);
|
||||
if (updateST0) {
|
||||
if (isForward)
|
||||
InstTable = ForwardST0Table;
|
||||
else
|
||||
InstTable = ReverseST0Table;
|
||||
} else {
|
||||
if (isForward)
|
||||
InstTable = ForwardSTiTable;
|
||||
else
|
||||
InstTable = ReverseSTiTable;
|
||||
}
|
||||
|
||||
int Opcode = Lookup(InstTable, ARRAY_SIZE(ForwardST0Table), MI->getOpcode());
|
||||
assert(Opcode != -1 && "Unknown TwoArgFP pseudo instruction!");
|
||||
|
||||
// NotTOS - The register which is not on the top of stack...
|
||||
unsigned NotTOS = (TOS == Op0) ? Op1 : Op0;
|
||||
|
||||
// Replace the old instruction with a new instruction
|
||||
*I = BuildMI(Opcode, 1).addReg(getSTReg(NotTOS));
|
||||
|
||||
// If both operands are killed, pop one off of the stack in addition to
|
||||
// overwriting the other one.
|
||||
if (KillsOp0 && KillsOp1 && Op0 != Op1) {
|
||||
assert(!updateST0 && "Should have updated other operand!");
|
||||
popStackAfter(I); // Pop the top of stack
|
||||
}
|
||||
|
||||
// Insert an explicit pop of the "updated" operand for FUCOM
|
||||
if (MI->getOpcode() == X86::FpUCOM) {
|
||||
if (KillsOp0 && !KillsOp1)
|
||||
popStackAfter(I); // If we kill the first operand, pop it!
|
||||
else if (KillsOp1 && Op0 != Op1) {
|
||||
if (getStackEntry(0) == Op1) {
|
||||
popStackAfter(I); // If it's right at the top of stack, just pop it
|
||||
} else {
|
||||
// Otherwise, move the top of stack into the dead slot, killing the
|
||||
// operand without having to add in an explicit xchg then pop.
|
||||
//
|
||||
unsigned STReg = getSTReg(Op1);
|
||||
unsigned OldSlot = getSlot(Op1);
|
||||
unsigned TopReg = Stack[StackTop-1];
|
||||
Stack[OldSlot] = TopReg;
|
||||
RegMap[TopReg] = OldSlot;
|
||||
RegMap[Op1] = ~0;
|
||||
Stack[--StackTop] = ~0;
|
||||
|
||||
MachineInstr *MI = BuildMI(X86::FSTPrr, 1).addReg(STReg);
|
||||
I = MBB->insert(I+1, MI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update stack information so that we know the destination register is now on
|
||||
// the stack.
|
||||
if (MI->getOpcode() != X86::FpUCOM) {
|
||||
unsigned UpdatedSlot = getSlot(updateST0 ? TOS : NotTOS);
|
||||
assert(UpdatedSlot < StackTop && Dest < 7);
|
||||
Stack[UpdatedSlot] = Dest;
|
||||
RegMap[Dest] = UpdatedSlot;
|
||||
}
|
||||
delete MI; // Remove the old instruction
|
||||
}
|
||||
|
||||
|
||||
/// handleSpecialFP - Handle special instructions which behave unlike other
|
||||
/// floating point instructions. This is primarily intended for use by pseudo
|
||||
/// instructions.
|
||||
///
|
||||
void FPS::handleSpecialFP(MachineBasicBlock::iterator &I) {
|
||||
MachineInstr *MI = *I;
|
||||
switch (MI->getOpcode()) {
|
||||
default: assert(0 && "Unknown SpecialFP instruction!");
|
||||
case X86::FpGETRESULT: // Appears immediately after a call returning FP type!
|
||||
assert(StackTop == 0 && "Stack should be empty after a call!");
|
||||
pushReg(getFPReg(MI->getOperand(0)));
|
||||
break;
|
||||
case X86::FpSETRESULT:
|
||||
assert(StackTop == 1 && "Stack should have one element on it to return!");
|
||||
--StackTop; // "Forget" we have something on the top of stack!
|
||||
break;
|
||||
case X86::FpMOV: {
|
||||
unsigned SrcReg = getFPReg(MI->getOperand(1));
|
||||
unsigned DestReg = getFPReg(MI->getOperand(0));
|
||||
bool KillsSrc = false;
|
||||
for (LiveVariables::killed_iterator KI = LV->killed_begin(MI),
|
||||
E = LV->killed_end(MI); KI != E; ++KI)
|
||||
KillsSrc |= KI->second == X86::FP0+SrcReg;
|
||||
|
||||
if (KillsSrc) {
|
||||
// If the input operand is killed, we can just change the owner of the
|
||||
// incoming stack slot into the result.
|
||||
unsigned Slot = getSlot(SrcReg);
|
||||
assert(Slot < 7 && DestReg < 7 && "FpMOV operands invalid!");
|
||||
Stack[Slot] = DestReg;
|
||||
RegMap[DestReg] = Slot;
|
||||
|
||||
} else {
|
||||
// For FMOV we just duplicate the specified value to a new stack slot.
|
||||
// This could be made better, but would require substantial changes.
|
||||
duplicateToTop(SrcReg, DestReg, I);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
I = MBB->erase(I)-1; // Remove the pseudo instruction
|
||||
}
|
|
@ -1,124 +0,0 @@
|
|||
//===-- InstSelectPattern.cpp - A pattern matching inst selector for X86 --===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines a pattern matching instruction selector for X86.
|
||||
//
|
||||
// FIXME: we could allocate one big array of unsigneds to use as the backing
|
||||
// store for all of the nodes costs arrays.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "X86.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/SSARegMap.h"
|
||||
|
||||
#include "X86RegisterInfo.h"
|
||||
|
||||
// Include the generated instruction selector...
|
||||
#include "X86GenInstrSelector.inc"
|
||||
|
||||
namespace {
|
||||
struct ISel : public FunctionPass, SelectionDAGTargetBuilder {
|
||||
TargetMachine &TM;
|
||||
ISel(TargetMachine &tm) : TM(tm) {}
|
||||
int VarArgsFrameIndex; // FrameIndex for start of varargs area
|
||||
|
||||
bool runOnFunction(Function &Fn) {
|
||||
MachineFunction &MF = MachineFunction::construct(&Fn, TM);
|
||||
SelectionDAG DAG(MF, TM, *this);
|
||||
|
||||
std::cerr << "\n\n\n=== "
|
||||
<< DAG.getMachineFunction().getFunction()->getName() << "\n";
|
||||
|
||||
DAG.dump();
|
||||
X86ISel(DAG).generateCode();
|
||||
std::cerr << "\n\n\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
public: // Implementation of the SelectionDAGTargetBuilder class...
|
||||
/// expandArguments - Add nodes to the DAG to indicate how to load arguments
|
||||
/// off of the X86 stack.
|
||||
void expandArguments(SelectionDAG &SD);
|
||||
void expandCall(SelectionDAG &SD, CallInst &CI);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void ISel::expandArguments(SelectionDAG &SD) {
|
||||
|
||||
// Add DAG nodes to load the arguments... On entry to a function on the X86,
|
||||
// the stack frame looks like this:
|
||||
//
|
||||
// [ESP] -- return address
|
||||
// [ESP + 4] -- first argument (leftmost lexically)
|
||||
// [ESP + 8] -- second argument, if first argument is four bytes in size
|
||||
// ...
|
||||
//
|
||||
MachineFunction &F = SD.getMachineFunction();
|
||||
MachineFrameInfo *MFI = F.getFrameInfo();
|
||||
const Function &Fn = *F.getFunction();
|
||||
|
||||
unsigned ArgOffset = 0; // Frame mechanisms handle retaddr slot
|
||||
for (Function::const_aiterator I = Fn.abegin(), E = Fn.aend(); I != E; ++I) {
|
||||
MVT::ValueType ObjectVT = SD.getValueType(I->getType());
|
||||
unsigned ArgIncrement = 4;
|
||||
unsigned ObjSize;
|
||||
switch (ObjectVT) {
|
||||
default: assert(0 && "Unhandled argument type!");
|
||||
case MVT::i8: ObjSize = 1; break;
|
||||
case MVT::i16: ObjSize = 2; break;
|
||||
case MVT::i32: ObjSize = 4; break;
|
||||
case MVT::i64: ObjSize = ArgIncrement = 8; break;
|
||||
case MVT::f32: ObjSize = 4; break;
|
||||
case MVT::f64: ObjSize = ArgIncrement = 8; break;
|
||||
}
|
||||
// Create the frame index object for this incoming parameter...
|
||||
int FI = MFI->CreateFixedObject(ObjSize, ArgOffset);
|
||||
|
||||
// Create the SelectionDAG nodes corresponding to a load from this parameter
|
||||
SelectionDAGNode *FIN = new SelectionDAGNode(ISD::FrameIndex, MVT::i32);
|
||||
FIN->addValue(new ReducedValue_FrameIndex_i32(FI));
|
||||
|
||||
SelectionDAGNode *Arg
|
||||
= new SelectionDAGNode(ISD::Load, ObjectVT, F.begin(), FIN);
|
||||
|
||||
// Add the SelectionDAGNodes to the SelectionDAG... note that there is no
|
||||
// reason to add chain nodes here. We know that no loads ore stores will
|
||||
// ever alias these loads, so we are free to perform the load at any time in
|
||||
// the function
|
||||
SD.addNode(FIN);
|
||||
SD.addNodeForValue(Arg, I);
|
||||
|
||||
ArgOffset += ArgIncrement; // Move on to the next argument...
|
||||
}
|
||||
|
||||
// If the function takes variable number of arguments, make a frame index for
|
||||
// the start of the first vararg value... for expansion of llvm.va_start.
|
||||
if (Fn.getFunctionType()->isVarArg())
|
||||
VarArgsFrameIndex = MFI->CreateFixedObject(1, ArgOffset);
|
||||
}
|
||||
|
||||
void ISel::expandCall(SelectionDAG &SD, CallInst &CI) {
|
||||
assert(0 && "ISel::expandCall not implemented!");
|
||||
}
|
||||
|
||||
|
||||
/// createX86PatternInstructionSelector - This pass converts an LLVM function
|
||||
/// into a machine code representation using pattern matching and a machine
|
||||
/// description file.
|
||||
///
|
||||
FunctionPass *createX86PatternInstructionSelector(TargetMachine &TM) {
|
||||
return new ISel(TM);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,133 +0,0 @@
|
|||
//===-- PeepholeOptimizer.cpp - X86 Peephole Optimizer --------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by the LLVM research group and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a peephole optimizer for the X86.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "X86.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
|
||||
namespace {
|
||||
struct PH : public MachineFunctionPass {
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
bool PeepholeOptimize(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator &I);
|
||||
|
||||
virtual const char *getPassName() const { return "X86 Peephole Optimizer"; }
|
||||
};
|
||||
}
|
||||
|
||||
FunctionPass *createX86PeepholeOptimizerPass() { return new PH(); }
|
||||
|
||||
bool PH::runOnMachineFunction(MachineFunction &MF) {
|
||||
bool Changed = false;
|
||||
|
||||
for (MachineFunction::iterator BI = MF.begin(), E = MF.end(); BI != E; ++BI)
|
||||
for (MachineBasicBlock::iterator I = BI->begin(); I != BI->end(); )
|
||||
if (PeepholeOptimize(*BI, I))
|
||||
Changed = true;
|
||||
else
|
||||
++I;
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
||||
|
||||
bool PH::PeepholeOptimize(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator &I) {
|
||||
MachineInstr *MI = *I;
|
||||
MachineInstr *Next = (I+1 != MBB.end()) ? *(I+1) : 0;
|
||||
unsigned Size = 0;
|
||||
switch (MI->getOpcode()) {
|
||||
case X86::MOVrr8:
|
||||
case X86::MOVrr16:
|
||||
case X86::MOVrr32: // Destroy X = X copies...
|
||||
if (MI->getOperand(0).getReg() == MI->getOperand(1).getReg()) {
|
||||
I = MBB.erase(I);
|
||||
delete MI;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
// A large number of X86 instructions have forms which take an 8-bit
|
||||
// immediate despite the fact that the operands are 16 or 32 bits. Because
|
||||
// this can save three bytes of code size (and icache space), we want to
|
||||
// shrink them if possible.
|
||||
case X86::ADDri16: case X86::ADDri32:
|
||||
case X86::SUBri16: case X86::SUBri32:
|
||||
case X86::IMULri16: case X86::IMULri32:
|
||||
case X86::ANDri16: case X86::ANDri32:
|
||||
case X86::ORri16: case X86::ORri32:
|
||||
case X86::XORri16: case X86::XORri32:
|
||||
assert(MI->getNumOperands() == 3 && "These should all have 3 operands!");
|
||||
if (MI->getOperand(2).isImmediate()) {
|
||||
int Val = MI->getOperand(2).getImmedValue();
|
||||
// If the value is the same when signed extended from 8 bits...
|
||||
if (Val == (signed int)(signed char)Val) {
|
||||
unsigned Opcode;
|
||||
switch (MI->getOpcode()) {
|
||||
default: assert(0 && "Unknown opcode value!");
|
||||
case X86::ADDri16: Opcode = X86::ADDri16b; break;
|
||||
case X86::ADDri32: Opcode = X86::ADDri32b; break;
|
||||
case X86::SUBri16: Opcode = X86::SUBri16b; break;
|
||||
case X86::SUBri32: Opcode = X86::SUBri32b; break;
|
||||
case X86::IMULri16: Opcode = X86::IMULri16b; break;
|
||||
case X86::IMULri32: Opcode = X86::IMULri32b; break;
|
||||
case X86::ANDri16: Opcode = X86::ANDri16b; break;
|
||||
case X86::ANDri32: Opcode = X86::ANDri32b; break;
|
||||
case X86::ORri16: Opcode = X86::ORri16b; break;
|
||||
case X86::ORri32: Opcode = X86::ORri32b; break;
|
||||
case X86::XORri16: Opcode = X86::XORri16b; break;
|
||||
case X86::XORri32: Opcode = X86::XORri32b; break;
|
||||
}
|
||||
unsigned R0 = MI->getOperand(0).getReg();
|
||||
unsigned R1 = MI->getOperand(1).getReg();
|
||||
*I = BuildMI(Opcode, 2, R0).addReg(R1).addZImm((char)Val);
|
||||
delete MI;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
#if 0
|
||||
case X86::MOVir32: Size++;
|
||||
case X86::MOVir16: Size++;
|
||||
case X86::MOVir8:
|
||||
// FIXME: We can only do this transformation if we know that flags are not
|
||||
// used here, because XOR clobbers the flags!
|
||||
if (MI->getOperand(1).isImmediate()) { // avoid mov EAX, <value>
|
||||
int Val = MI->getOperand(1).getImmedValue();
|
||||
if (Val == 0) { // mov EAX, 0 -> xor EAX, EAX
|
||||
static const unsigned Opcode[] ={X86::XORrr8,X86::XORrr16,X86::XORrr32};
|
||||
unsigned Reg = MI->getOperand(0).getReg();
|
||||
*I = BuildMI(Opcode[Size], 2, Reg).addReg(Reg).addReg(Reg);
|
||||
delete MI;
|
||||
return true;
|
||||
} else if (Val == -1) { // mov EAX, -1 -> or EAX, -1
|
||||
// TODO: 'or Reg, -1' has a smaller encoding than 'mov Reg, -1'
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#endif
|
||||
case X86::BSWAPr32: // Change bswap EAX, bswap EAX into nothing
|
||||
if (Next->getOpcode() == X86::BSWAPr32 &&
|
||||
MI->getOperand(0).getReg() == Next->getOperand(0).getReg()) {
|
||||
I = MBB.erase(MBB.erase(I));
|
||||
delete MI;
|
||||
delete Next;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
; RUN: export PATH=/usr/bin:/bin/:${PATH}
|
||||
; RUN: PATH=/usr/bin:/bin/:${PATH}
|
||||
; RUN: export PATH
|
||||
; RUN: bugpoint %s -dce -bugpoint-deletecalls -simplifycfg
|
||||
|
||||
%.LC0 = internal global [13 x sbyte] c"Hello World\0A\00"
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
LEVEL = ..
|
||||
DIRS = Programs
|
||||
include Makefile.tests
|
||||
|
||||
#
|
||||
# Make QMTest the default for testing features and regressions
|
||||
# Do this first to force QMTest to run first
|
||||
#
|
||||
all:: qmtest
|
||||
|
||||
#
|
||||
# Include other test rules
|
||||
#
|
||||
include Makefile.tests
|
||||
|
||||
#
|
||||
# New QMTest functionality:
|
||||
# The test suite is being transitioned over to QMTest. Eventually, it
|
||||
|
|
Loading…
Reference in New Issue
Block a user