Compare commits

...

17 Commits

Author SHA1 Message Date
John Criswell
303b238cc3 Updated code and source sizes.
Fixed some minor typos.

llvm-svn: 12513
2004-03-19 21:59:23 +00:00
John Criswell
c1d8934838 Not ready for prime time.
llvm-svn: 12512
2004-03-19 20:57:39 +00:00
John Criswell
3c96135937 Updated to latest revision in the trunk.
Fixed some typos.

llvm-svn: 12511
2004-03-19 20:08:17 +00:00
John Criswell
3c0d59f546 Added a remark about setting LLVM_LIB_SEARCH_PATH. I forgot to do this on
PowerPC, and it made the test results scary.

llvm-svn: 12509
2004-03-19 17:00:35 +00:00
John Criswell
510529f5e1 Merged in Chris's fix from trunk (revision 1.138).
llvm-svn: 12508
2004-03-19 15:11:25 +00:00
John Criswell
df834c2b61 Removed PowerPC directory.
llvm-svn: 12503
2004-03-18 17:47:49 +00:00
John Criswell
d0118041ec Removing the PowerPC code generator from the LLVM 1.2 Release Tree.
This is good because it will make LLVM more "polished," but bad because
there might be a joe out there who could take this and flesh it out into
a real code generator.

llvm-svn: 12502
2004-03-18 17:47:08 +00:00
John Criswell
87340561e3 Removed PowerPC code generation options from llc. The PowerPC code
generator isn't even at an experimental stage (if I understand the comments
correctly).

llvm-svn: 12501
2004-03-18 17:32:36 +00:00
John Criswell
d118722f63 Gave Darwin its own expectations file.
llvm-svn: 12499
2004-03-18 16:41:59 +00:00
John Criswell
052debc4d8 Updated code from trunk.
llvm-svn: 12498
2004-03-18 16:41:44 +00:00
John Criswell
9f115d2063 cvs slurp revision 1.14 from mainline.
llvm-svn: 12497
2004-03-18 15:04:57 +00:00
John Criswell
e2fb1d0251 Defined the NO_DUMMY_DECL variable. This removes the zlib hack that
for "bad compilers" that generates a type conflict resolution error when
linking zlib with gccld.

llvm-svn: 12478
2004-03-17 23:12:00 +00:00
John Criswell
3c5f2201c9 Slurping up Revision 1.25 of this document, which is described as:
"Rewrite the second on AnalysisUsage usage.  This documents the new
addRequiredTransitive member that Misha added, and explains the whole
concept a lot better.  Also, the document used incorrect "subsubsection"
tags instead of "doc_subsubsection" which this fixes."

llvm-svn: 12476
2004-03-17 21:22:18 +00:00
John Criswell
3f024e982f Removed the -dsa-track-integers option.
llvm-svn: 12475
2004-03-17 21:20:14 +00:00
John Criswell
51a4de5f2e Updated options for release 1.2.
llvm-svn: 12473
2004-03-17 20:58:09 +00:00
John Criswell
6babfa929c Added information about how to get QMTest 2.0.3.
llvm-svn: 12472
2004-03-17 20:07:32 +00:00
CVS to SVN Conversion
bb8b55b1e4 This commit was manufactured by cvs2svn to create branch 'release_12'.
llvm-svn: 12471
2004-03-17 17:42:09 +00:00
43 changed files with 339 additions and 2784 deletions

View File

@@ -53,11 +53,6 @@ language.
list of available analysis passes.
<p>
<li> -dsa-track-integers
<br>
Track integers as potential pointers.
<p>
<li> -profile-info-file &lt;filename&gt;
<br>
Specify the name of the file loaded by the -profile-loader option.

View File

@@ -190,6 +190,16 @@ non-obvious ways. Here are some hints and tips:<p>
when attempting to reduce test programs. If you're trying to find
a bug in one of these passes, <tt>bugpoint</tt> may crash.<p>
<li><tt>-enable-correct-eh-support</tt><br>
Make the -lowerinvoke pass insert expensive, but correct, exception
handling code.<p>
<li><tt>-internalize-public-api-file &lt;filename&gt;</tt><br>
Preserve the symbols listed in the file <tt>filename</tt>.<p>
<li><tt>-internalize-public-api-list &lt;list&gt;</tt><br>
Preserve the symbols listed in <tt>list</tt>.<p>
<li> <tt>-help</tt><br>
Print a summary of command line options.<p>
@@ -215,6 +225,9 @@ non-obvious ways. Here are some hints and tips:<p>
<tt>bugpoint</tt> will attempt to generate a reference output by
compiling the program with the C backend and running it.<p>
<li><tt>-profile-info-file &lt;filename&gt;</tt><br>
Profile file loaded by -profile-loader.<p>
<a name="opt_run-"><li><tt>-run-{int,jit,llc,cbe}</tt><br>
Whenever the test program is compiled, <tt>bugpoint</tt> should generate
code for it using the specified code generator. These options allow

View File

@@ -53,11 +53,6 @@ writes its output to the standard output.
Specify the output filename.
<p>
<li> -dsa-track-integers
<br>
Track integers as potential pointers.
<p>
<li> -profile-info-file &lt;filename&gt;
<br>
Specify the name of the file loaded by the -profile-loader option.

View File

@@ -49,6 +49,8 @@
<li>I've built LLVM and am testing it, but the tests freeze.</li>
<li>Why do test results differ when I perform different types of builds?</li>
<li>Compiling LLVM with GCC 3.3.2 fails, what should I do?</li>
<li>When I use the test suite, all of the C Backend tests fail. What is
wrong?</li>
</ol></li>
<li><a href="#cfe">Using the GCC Front End</a>
@@ -338,6 +340,31 @@ build.</p>
affects projects other than LLVM. Try upgrading or downgrading your GCC.</p>
</div>
<div class="question">
<p>
When I use the test suite, all of the C Backend tests fail. What is
wrong?
</p>
</div>
<div class="answer">
<p>
If you build LLVM and the C Backend tests fail in <tt>llvm/test/Programs</tt>,
then chances are good that the directory pointed to by the LLVM_LIB_SEARCH_PATH
environment variable does not contain the libcrtend.a library.
</p>
<p>
To fix it, verify that LLVM_LIB_SEARCH_PATH points to the correct directory
and that libcrtend.a is inside. For pre-built LLVM GCC front ends, this
should be the absolute path to
<tt>cfrontend/&lt;<i>platform</i>&gt;/llvm-gcc/bytecode-libs</tt>. If you've
built your own LLVM GCC front end, then ensure that you've built and installed
the libraries in <tt>llvm/runtime</tt> and have LLVM_LIB_SEARCH_PATH pointing
to the <tt>LLVMGCCDIR/bytecode-libs</tt> subdirectory.
</p>
</div>
<!-- *********************************************************************** -->
<div class="doc_section">
<a name="cfe">Using the GCC Front End</a>

View File

@@ -182,10 +182,10 @@ software you will need.</p>
<li>Linux on x86 (Pentium and above)
<ul>
<li>Approximately 918 MB of Free Disk Space
<li>Approximately 1.02 GB of Free Disk Space
<ul>
<li>Source code: 28 MB</li>
<li>Object code: 850 MB</li>
<li>Source code: 45 MB</li>
<li>Object code: 956 MB</li>
<li>GCC front end: 40 MB</li>
</ul></li>
</ul>
@@ -193,10 +193,10 @@ software you will need.</p>
<li>Solaris on SparcV9 (Ultrasparc)
<ul>
<li>Approximately 1.52 GB of Free Disk Space
<li>Approximately 1.75 GB of Free Disk Space
<ul>
<li>Source code: 28 MB</li>
<li>Object code: 1470 MB</li>
<li>Source code: 45 MB</li>
<li>Object code: 1705 MB</li>
<li>GCC front end: 50 MB</li>
</ul></li>
</ul>
@@ -204,9 +204,9 @@ software you will need.</p>
<li>FreeBSD on x86 (Pentium and above)
<ul>
<li>Approximately 918 MB of Free Disk Space
<li>Approximately 935 MB of Free Disk Space
<ul>
<li>Source code: 28 MB</li>
<li>Source code: 45 MB</li>
<li>Object code: 850 MB</li>
<li>GCC front end: 40 MB</li>
</ul></li>
@@ -216,9 +216,9 @@ software you will need.</p>
<li>MacOS X on PowerPC
<ul>
<li>No native code generation
<li>Approximately 1.20 GB of Free Disk Space
<li>Approximately 1.25 GB of Free Disk Space
<ul>
<li>Source code: 28 MB</li>
<li>Source code: 45 MB</li>
<li>Object code: 1160 MB</li>
<li>GCC front end: 40 MB</li>
</ul></li>
@@ -274,10 +274,23 @@ LLVM:</p>
automake from 1.4p5 on should work; we only use aclocal from that
package.</p></li>
<li><A href="http://www.codesourcery.com/qm/qmtest">QMTest</A></li>
<li><A href="http://www.codesourcery.com/qm/qmtest">QMTest 2.0.3</A></li>
<li><A href="http://www.python.org">Python</A>
<p>These are needed to use the LLVM test suite.</p></li>
<p>
These are needed to use the LLVM test suite. Please note that newer
versions of QMTest may not work with the LLVM test suite. QMTest 2.0.3
can be retrieved from the QMTest CVS repository using the following
commands:
<ul>
<li><tt>cvs -d :pserver:anoncvs@cvs.codesourcery.com:/home/qm/Repository login</tt>
</li>
<li>When prompted, use <tt>anoncvs</tt> as the password.
</li>
<li><tt>cvs -d :pserver:anoncvs@cvs.codesourcery.com:/home/qm/Repository co -r release-2-0-3 qm</tt>
</li>
</ul>
</p></li>
</ul>
@@ -858,7 +871,7 @@ different <a href="#tools">tools</a>.</p>
<dt><tt>llvm/lib/Target/</tt><dd> This directory contains files that
describe various target architectures for code generation. For example,
the llvm/lib/Target/Sparc directory holds the Sparc machine
the llvm/lib/Target/SparcV9 directory holds the Sparc machine
description.<br>
<dt><tt>llvm/lib/CodeGen/</tt><dd> This directory contains the major parts

View File

@@ -1,180 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<link rel="stylesheet" href="llvm.css" type="text/css">
<title>LLVM vs. the World - Comparing Compilers to Compilers</title>
</head>
<body>
<div class="doc_title">
LLVM vs. the World - Comparing Compilers to Compilers
</div>
<ol>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#generalapplicability">General Applicability</a></li>
<li><a href="#typesystem">Type System</a></li>
<li><a href="#dataflowinformation">Control-flow and Data-flow Information</a></li>
<li><a href="#registers">Registers</a></li>
<li><a href="#programmerinterface">Programmer Interface</a></li>
<li><a href="#codeemission">Machine Code Emission</a></li>
</ol>
<div class="doc_text">
<p><b>Written by Brian R. Gaeke</b></p>
</div>
<!-- *********************************************************************** -->
<div class="doc_section">
<a name="introduction">Introduction</a>
</div>
<!-- *********************************************************************** -->
<div class="doc_text">
<p>Whether you are a stranger to LLVM or not, and whether you are considering
using it for your projects or not, you may find it useful to understand how we
compare ourselves to other well-known compilers. The following list of points
should help you understand -- from our point of view -- some of the important
ways in which we see LLVM as different from other selected compilers and
code generation systems.</p>
<p>At the moment, we only compare ourselves below to <a
href="http://gcc.gnu.org/">GCC</a> and <a
href="http://www.gnu.org/software/lightning/">GNU lightning</a>, but we will try
to revise and expand it as our knowledge and experience permit. Contributions are
welcome.</p>
</div>
<!-- *********************************************************************** -->
<div class="doc_section">
<a name="generalapplicability">General Applicability</a>
</div>
<!-- *********************************************************************** -->
<div class="doc_text">
<p>GNU lightning: Only currently usable for dynamic runtime emission of binary
machine code to memory. Supports one backend at a time.</p>
<p>LLVM: Supports compilation of C and C++ (with more languages coming soon),
strong SSA-based optimization at compile-time, link-time, run-time, and
off-line, and multiple platform backends with Just-in-Time and ahead-of-time
compilation frameworks. (See our document on <a
href="http://llvm.cs.uiuc.edu/pubs/2004-01-30-CGO-LLVM.html">Lifelong
Code Optimization</a> for more.)</p>
<p>GCC: Many relatively mature platform backends support assembly-language code
generation from many source languages. No run-time compilation
support.</p>
</div>
<!-- *********************************************************************** -->
<div class="doc_section">
<a name="typesystem">Type System</a>
</div>
<!-- *********************************************************************** -->
<div class="doc_text">
<p>GNU lightning: C integer types and "void *" are supported. No type checking
is performed. Explicit type casts are not typically necessary unless the
underlying machine-specific types are distinct (e.g., sign- or zero-extension is
apparently necessary, but casting "int" to "void *" would not be.)
Floating-point support may not work on all platforms (it does not appear to be
documented in the latest release).</p>
<p>LLVM: Compositional type system based on C types, supporting structures,
opaque types, and C integer and floating point types. Explicit cast instructions
are required to transform a value from one type to another.</p>
<p>GCC: Union of high-level types including those used in Pascal, C, C++, Ada,
Java, and FORTRAN.</p>
</div>
<!-- *********************************************************************** -->
<div class="doc_section">
<a name="dataflowinformation">Control-flow and Data-flow Information</a>
</div>
<!-- *********************************************************************** -->
<div class="doc_text">
<p>GNU lightning: No data-flow information encoded in the generated program. No
support for calculating CFG or def-use chains over generated programs.</p>
<p>LLVM: Scalar values in Static Single-Assignment form; def-use chains and CFG
always implicitly available and automatically kept up to date.</p>
<p>GCC: Trees and RTL do not directly encode data-flow info; but def-use chains
and CFGs can be calculated on the side. They are not automatically kept up to
date.</p>
</div>
<!-- *********************************************************************** -->
<div class="doc_section">
<a name="registers">Registers</a>
</div>
<!-- *********************************************************************** -->
<div class="doc_text">
<p>GNU lightning: Very small fixed register set -- it takes the least common
denominator of supported platforms; basically it inherits its tiny register set
from IA-32, unnecessarily crippling targets like PowerPC with a large register
set.</p>
<p>LLVM: An infinite register set, reduced to a particular platform's finite
register set by register allocator.</p>
<p>GCC: Trees and RTL provide an arbitrarily large set of values. Reduced to a
particular platform's finite register set by register allocator.</p>
</div>
<!-- *********************************************************************** -->
<div class="doc_section">
<a name="programmerinterface">Programmer Interface</a>
</div>
<!-- *********************************************************************** -->
<div class="doc_text">
<p>GNU lightning: Library interface based on C preprocessor macros that emit
binary code for a particular instruction to memory. No support for manipulating
code before emission.</p>
<p>LLVM: Library interface based on classes representing platform-independent
intermediate code (Instruction) and platform-dependent code (MachineInstr) which
can be manipulated arbitrarily and then emitted to memory.</p>
<p>GCC: Internal header file interface (tree.h) to abstract syntax trees,
representing roughly the union of all possible supported source-language
constructs; also, an internal header file interface (rtl.h, rtl.def) to a
low-level IR called RTL which represents roughly the union of all possible
target machine instructions.</p>
</div>
<!-- *********************************************************************** -->
<div class="doc_section">
<a name="codeemission">Machine Code Emission</a>
</div>
<!-- *********************************************************************** -->
<div class="doc_text">
<p>GNU lightning: Only supports binary machine code emission to memory.</p>
<p>LLVM: Supports writing out assembly language to a file, and binary machine
code to memory, from the same back-end.</p>
<p>GCC: Supports writing out assembly language to a file. No support for
emitting machine code to memory.</p>
</div>
<!-- *********************************************************************** -->
<hr>
<div class="doc_footer">
<address>Brian R. Gaeke</address>
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
<br>
Last modified: $Date$
</div>
</body>
</html>

View File

@@ -121,12 +121,12 @@ href="http://llvm.cs.uiuc.edu/PR203">RPM package generation</a>.</li>
</ul>
</li>
<li><a href="http://llvm.cs.uiuc.edu/PR253">LLVM now no longer depends on the boost library</a>.</li>
<li>The X86 backend now generates <b>substantially</b> better native code, and is faster.</li>
<li>The X86 backend now generates <b>substantially</b> better native code and is faster.</li>
<li>The C backend has been turned moved from the "llvm-dis" tool to the "llc"
tool. You can activate it with "<tt>llc -march=c foo.bc -o foo.c</tt>".</li>
<li>LLVM includes a new interprocedural optimization that marks global variables
"constant" when they are provably never written to.</li>
<li>LLVM now includes a new interprocedural optimization that converts small "by reference" arguments to "by value" arguments, which is often improve the performance of C++ programs substantially.</li>
<li>LLVM now includes a new interprocedural optimization that converts small "by reference" arguments to "by value" arguments, which often improves the performance of C++ programs substantially.</li>
<li>Bugpoint can now do a better job reducing miscompilation problems by
reducing programs down to a particular loop nest, instead of just the function
being miscompiled.</li>
@@ -145,7 +145,7 @@ In this release, the following missing features were implemented:
<ol>
<li><a href="http://llvm.cs.uiuc.edu/PR16">Exception handling in the X86
&amp; Sparc native code generators</a> is now supported</li>
<li>The C/C++ front-end now support the GCC <tt>__builtin_return_address</tt> and <tt>__builtin_frame_address</tt> extensions. These are also supported by the X86 backend and by the C backend.</li>
<li>The C/C++ front-end now supports the GCC <tt>__builtin_return_address</tt> and <tt>__builtin_frame_address</tt> extensions. These are also supported by the X86 backend and by the C backend.</li>
<li><a href="http://llvm.cs.uiuc.edu/PR249">[X86] Missing cast from ULong -> Double, cast FP -> bool and support for -9223372036854775808</a></li>
<li>The C/C++ front-end <a href="http://llvm.cs.uiuc.edu/PR273">now supports</a>
the "<a href="http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html#Labels%20as%20Values">labels as values</a>" GCC extension, often used to build "threaded interpreters".</a></li>
@@ -231,7 +231,7 @@ cause use of invalid pointers!</a></li>
<li><a href="http://llvm.cs.uiuc.edu/PR274">[JIT] Programs cannot resolve the fstat function</a></li>
<li><a href="http://llvm.cs.uiuc.edu/PR284">[indvars] Induction variable analysis violates LLVM invariants</a></li>
<li><a href="http://llvm.cs.uiuc.edu/PR296">[execution engines] Unhandled cast constant expression</a></li>
<li><a href="http://llvm.cs.uiuc.edu/PR299">[Sparc] Code generator asserts on alloca of zero size type</a></li>
</ol>
@@ -602,7 +602,7 @@ href="http://gcc.gnu.org/gcc-3.4/changes.html">GCC 3.4 release notes</a>.</li>
<div class="doc_text">
<ul>
<li>None so far.
<li>There are several programs in the LLVM testsuite that the Sparc code generator is known to miscompile.</li>
</ul>
</div>

View File

@@ -59,7 +59,10 @@
<ul>
<li><a href="#getAnalysisUsage">The <tt>getAnalysisUsage</tt>
method</a></li>
<li><a href="#getAnalysis">The <tt>getAnalysis</tt> method</a></li>
<li><a href="#AU::addRequired">The <tt>AnalysisUsage::addRequired&lt;&gt;</tt> and <tt>AnalysisUsage::addRequiredTransitive&lt;&gt;</tt> methods</a></li>
<li><a href="#AU::addPreserved">The <tt>AnalysisUsage::addPreserved&lt;&gt;</tt> method</a></li>
<li><a href="#AU::examples">Example implementations of <tt>getAnalysisUsage</tt></a></li>
<li><a href="#getAnalysis">The <tt>getAnalysis&lt;&gt;</tt> and <tt>getAnalysisToUpdate&lt;&gt;</tt> methods</a></li>
</ul></li>
<li><a href="#analysisgroup">Implementing Analysis Groups</a>
<ul>
@@ -171,12 +174,9 @@ include $(LEVEL)/Makefile.common
<p>This makefile specifies that all of the <tt>.cpp</tt> files in the current
directory are to be compiled and linked together into a
<tt>lib/Debug/libhello.so</tt> shared object that can be dynamically loaded by
the <tt>opt</tt> or <tt>analyze</tt> tools.</p>
<p>
Note that the suffix of the shared library may differ from the example above if
your system uses a different suffix by default.
</p>
the <tt>opt</tt> or <tt>analyze</tt> tools. If your operating system uses a
suffix other than .so (such as windows of Mac OS/X), the appropriate extension
will be used.</p>
<p>Now that we have the build scripts set up, we just need to write the code for
the pass itself.</p>
@@ -487,7 +487,7 @@ should return true if they modified the program, or false if they didn't.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="doInitialization_mod">The <tt>doInitialization(Module &amp;)</tt>
method</a>
</div>
@@ -516,7 +516,7 @@ free functions that it needs, adding prototypes to the module if necessary.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="runOnFunction">The <tt>runOnFunction</tt> method</a>
</div>
@@ -533,7 +533,7 @@ be returned if the function is modified.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="doFinalization_mod">The <tt>doFinalization(Module
&amp;)</tt> method</a>
</div>
@@ -581,7 +581,7 @@ href="#FunctionPass"><tt>FunctionPass</tt></a>'s have, but also have the followi
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="doInitialization_fn">The <tt>doInitialization(Function
&amp;)</tt> method</a>
</div>
@@ -603,7 +603,7 @@ fast).</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="runOnBasicBlock">The <tt>runOnBasicBlock</tt> method</a>
</div>
@@ -621,7 +621,7 @@ if the basic block is modified.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="doFinalization_fn">The <tt>doFinalization(Function &amp;)</tt>
method</a>
</div>
@@ -647,14 +647,12 @@ finalization.</p>
<div class="doc_text">
<p>A <tt>MachineFunctionPass</tt> executes on the machine-dependent
representation of each LLVM function in the program,
independent of all of the other functions in the program.
A <tt>MachineFunctionPass</tt> is also a <tt>FunctionPass</tt>, so all
<p>A <tt>MachineFunctionPass</tt> is a part of the LLVM code generator that
executes on the machine-dependent representation of each LLVM function in the
program. A <tt>MachineFunctionPass</tt> is also a <tt>FunctionPass</tt>, so all
the restrictions that apply to a <tt>FunctionPass</tt> also apply to it.
<tt>MachineFunctionPass</tt>es also have additional restrictions. In
particular, <tt>MachineFunctionPass</tt>es are not allowed to do any of
the following:</p>
<tt>MachineFunctionPass</tt>es also have additional restrictions. In particular,
<tt>MachineFunctionPass</tt>es are not allowed to do any of the following:</p>
<ol>
<li>Modify any LLVM Instructions, BasicBlocks or Functions.</li>
@@ -669,7 +667,7 @@ data)</li>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="runOnMachineFunction">The <tt>runOnMachineFunction(MachineFunction
&amp;MF)</tt> method</a>
</div>
@@ -718,11 +716,7 @@ registering a pass that logically should be available for use in the
<li><b><tt>RegisterAnalysis</tt></b> - This template should be used when you are
registering a pass that logically should be available for use in the
'<tt>analysis</tt>' utility.</li>
<li><b><tt>RegisterLLC</tt></b> - This template should be used when you are
registering a pass that logically should be available for use in the
'<tt>llc</tt>' utility.</li>
'<tt>analyze</tt>' utility.</li>
<li><b><tt>RegisterPass</tt></b> - This is the generic form of the
<tt>Register*</tt> templates that should be used if you want your pass listed by
@@ -740,14 +734,6 @@ example <tt>opt</tt> or <tt>analyze</tt>). The second argument is the name of
the pass, which is to be used for the <tt>--help</tt> output of programs, as
well as for debug output generated by the <tt>--debug-pass</tt> option.</p>
<p>If you pass is constructed by its default constructor, you only ever have to
pass these two arguments. If, on the other hand, you require other information
(like target specific information), you must pass an additional argument. This
argument is a pointer to a function used to create the pass. For an example of
how this works, look at the <a
href="http://llvm.cs.uiuc.edu/doxygen/LowerAllocations_8cpp-source.html">LowerAllocations.cpp</a>
file.</p>
<p>If a pass is registered to be used by the <tt>analyze</tt> utility, you
should implement the virtual <tt>print</tt> method:</p>
@@ -819,34 +805,77 @@ invalidated sets may be specified for your transformation. The implementation
should fill in the <tt><a
href="http://llvm.cs.uiuc.edu/doxygen/classllvm_1_1AnalysisUsage.html">AnalysisUsage</a></tt>
object with information about which passes are required and not invalidated. To
do this, the following set methods are provided by the <tt><a
href="http://llvm.cs.uiuc.edu/doxygen/classllvm_1_1AnalysisUsage.html">AnalysisUsage</a></tt>
class:</p>
do this, a pass may call any of the following methods on the AnalysisUsage
object:</p>
</div>
<pre>
<i>// addRequires - Add the specified pass to the required set for your pass.</i>
<b>template</b>&lt;<b>class</b> PassClass&gt;
AnalysisUsage &amp;AnalysisUsage::addRequired();
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="AU::addRequired">The <tt>AnalysisUsage::addRequired&lt;&gt;</tt> and <tt>AnalysisUsage::addRequiredTransitive&lt;&gt;</tt> methods</a>
</div>
<i>// addPreserved - Add the specified pass to the set of analyses preserved by
// this pass</i>
<b>template</b>&lt;<b>class</b> PassClass&gt;
AnalysisUsage &amp;AnalysisUsage::addPreserved();
<div class="doc_text">
<p>
If you pass requires a previous pass to be executed (an analysis for example),
it can use one of these methods to arrange for it to be run before your pass.
LLVM has many different types of analyses and passes that can be required,
spaning the range from <tt>DominatorSet</tt> to <tt>BreakCriticalEdges</tt>.
requiring <tt>BreakCriticalEdges</tt>, for example, guarantees that there will
be no critical edges in the CFG when your pass has been run.
</p>
<i>// setPreservesAll - Call this if the pass does not modify its input at all</i>
<b>void</b> AnalysisUsage::setPreservesAll();
<p>
Some analyses chain to other analyses to do their job. For example, an <a
href="AliasAnalysis.html">AliasAnalysis</a> implementation is required to <a
href="AliasAnalysis.html#chaining">chain</a> to other alias analysis passes. In
cases where analyses chain, the <tt>addRequiredTransitive</tt> method should be
used instead of the <tt>addRequired</tt> method. This informs the PassManager
that the transitively required pass should be alive as long as the requiring
pass is.
</p>
</div>
<i>// setPreservesCFG - This function should be called by the pass, iff they do not:
//
// 1. Add or remove basic blocks from the function
// 2. Modify terminator instructions in any way.
//
// This is automatically implied for <a href="#BasicBlockPass">BasicBlockPass</a>'s
//</i>
<b>void</b> AnalysisUsage::setPreservesCFG();
</pre>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="AU::addPreserved">The <tt>AnalysisUsage::addPreserved&lt;&gt;</tt> method</a>
</div>
<p>Some examples of how to use these methods are:</p>
<div class="doc_text">
<p>
One of the jobs of the PassManager is to optimize how and when analyses are run.
In particular, it attempts to avoid recomputing data unless it needs to. For
this reason, passes are allowed to declare that they preserve (i.e., they don't
invalidate) an existing analysis if it's available. For example, a simple
constant folding pass would not modify the CFG, so it can't possible effect the
results of dominator analysis. By default, all passes are assumed to invalidate
all others.
</p>
<p>
The <tt>AnalysisUsage</tt> class provides several methods which are useful in
certain circumstances that are related to <tt>addPreserved</tt>. In particular,
the <tt>setPreservesAll</tt> method can be called to indicate that the pass does
not modify the LLVM program at all (which is true for analyses), and the
<tt>setPreservesCFG</tt> method can be used by transformations that change
instructions in the program but do not modify the CFG or terminator instructions
(note that this property is implicitly set for <a
href="#BasicBlockPass">BasicBlockPass</a>'s).
</p>
<p>
<tt>addPreserved</tt> is particularly useful for transformations like
<tt>BreakCriticalEdges</tt>. This pass knows how to update a small set of loop
and dominator related analyses if they exist, so it can preserve them, despite
the fact that it hacks on the CFG.
</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="AU::examples">Example implementations of <tt>getAnalysisUsage</tt></a>
</div>
<div class="doc_text">
<pre>
<i>// This is an example implementation from an analysis, which does not modify
@@ -871,20 +900,22 @@ class:</p>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="getAnalysis">The <tt>getAnalysis&lt;&gt;</tt> method</a>
<a name="getAnalysis">The <tt>getAnalysis&lt;&gt;</tt> and <tt>getAnalysisToUpdate&lt;&gt;</tt> methods</a>
</div>
<div class="doc_text">
<p>The <tt>Pass::getAnalysis&lt;&gt;</tt> method is inherited by your class,
providing you with access to the passes that you declared that you required with
the <a href="#getAnalysisUsage"><tt>getAnalysisUsage</tt></a> method. It takes
a single template argument that specifies which pass class you want, and returns
a reference to that pass.</p>
<p>The <tt>Pass::getAnalysis&lt;&gt;</tt> method is automatically inherited by
your class, providing you with access to the passes that you declared that you
required with the <a href="#getAnalysisUsage"><tt>getAnalysisUsage</tt></a>
method. It takes a single template argument that specifies which pass class you
want, and returns a reference to that pass. For example:</p>
<pre>
<b>template</b>&lt;<b>typename</b> PassClass&gt;
AnalysisType &amp;getAnalysis();
bool LICM::runOnFunction(Function &F) {
LoopInfo &amp;LI = getAnalysis&lt;LoopInfo&gt;();
...
}
</pre>
<p>This method call returns a reference to the pass desired. You may get a
@@ -894,6 +925,20 @@ href="#getAnalysisUsage"><tt>getAnalysisUsage</tt></a> implementation. This
method can be called by your <tt>run*</tt> method implementation, or by any
other local method invoked by your <tt>run*</tt> method.</p>
<p>
If your pass is capable of updating analyses if they exist (e.g.,
<tt>BreakCriticalEdges</tt>, as described above), you can use the
<tt>getAnalysisToUpdate</tt> method, which returns a pointer to the analysis if
it is active. For example:</p>
<pre>
...
if (DominatorSet *DS = getAnalysisToUpdate&lt;DominatorSet&gt;()) {
<i>// A DominatorSet is active. This code will update it.</i>
}
...
</pre>
</div>
<!-- *********************************************************************** -->
@@ -924,7 +969,7 @@ Analysis Groups.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="agconcepts">Analysis Group Concepts</a>
</div>
@@ -975,7 +1020,7 @@ hypothetical example) instead.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="registerag">Using <tt>RegisterAnalysisGroup</tt></a>
</div>
@@ -1345,7 +1390,7 @@ where we are going:</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="SMP">Multithreaded LLVM</a>
</div>
@@ -1368,7 +1413,7 @@ Despite that, we have kept the LLVM passes SMP ready, and you should too.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="ModuleSource">A new <tt>ModuleSource</tt> interface</a>
</div>
@@ -1395,7 +1440,7 @@ capable of this, the loader just needs to be reworked a bit.</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="subsubsection">
<div class="doc_subsubsection">
<a name="PassFunctionPass"><tt>Pass</tt>es requiring <tt>FunctionPass</tt>es</a>
</div>

View File

@@ -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

View File

@@ -14,23 +14,26 @@
#ifndef LLVM_TRANSFORMS_UTILS_FUNCTION_H
#define LLVM_TRANSFORMS_UTILS_FUNCTION_H
#include <vector>
namespace llvm {
class BasicBlock;
class DominatorSet;
class Function;
class Loop;
/// ExtractCodeRegion - rip out a sequence of basic blocks into a new function
///
Function* ExtractCodeRegion(DominatorSet &DS,
const std::vector<BasicBlock*> &code);
class Function;
class Loop;
/// ExtractCodeRegion - rip out a sequence of basic blocks into a new function
///
Function* ExtractCodeRegion(const std::vector<BasicBlock*> &code);
/// ExtractLoop - rip out a natural loop into a new function
///
Function* ExtractLoop(Loop *L);
/// ExtractBasicBlock - rip out a basic block into a new function
///
Function* ExtractBasicBlock(BasicBlock *BB);
/// ExtractLoop - rip out a natural loop into a new function
///
Function* ExtractLoop(DominatorSet &DS, Loop *L);
/// ExtractBasicBlock - rip out a basic block into a new function
///
Function* ExtractBasicBlock(BasicBlock *BB);
}
#endif

View File

@@ -101,7 +101,7 @@ void AliasSet::addCallSite(CallSite CS, AliasAnalysis &AA) {
return;
else if (AA.onlyReadsMemory(F)) {
AliasTy = MayAlias;
AccessTy = Refs;
AccessTy |= Refs;
return;
}
}

View File

@@ -7,7 +7,7 @@
#
##===----------------------------------------------------------------------===##
LEVEL = ../..
DIRS = CBackend X86 SparcV9 PowerPC
DIRS = CBackend X86 SparcV9
LIBRARYNAME = target
BUILD_ARCHIVE = 1

View File

@@ -1,42 +0,0 @@
//===-- PowerPC.h - Top-level interface for PowerPC representation -*- 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 entry points for global functions defined in the LLVM
// PowerPC back-end.
//
//===----------------------------------------------------------------------===//
#ifndef TARGET_POWERPC_H
#define TARGET_POWERPC_H
#include <iosfwd>
namespace llvm {
class FunctionPass;
class TargetMachine;
// Here is where you would define factory methods for powerpc-specific
// passes. For example:
// FunctionPass *createPowerPCSimpleInstructionSelector (TargetMachine &TM);
// FunctionPass *createPowerPCCodePrinterPass(std::ostream &OS,
// TargetMachine &TM);
} // end namespace llvm;
// Defines symbolic names for PowerPC registers. This defines a mapping from
// register name to register number.
//
#include "PowerPCGenRegisterNames.inc"
// Defines symbolic names for the PowerPC instructions.
//
#include "PowerPCGenInstrNames.inc"
#endif

View File

@@ -1,46 +0,0 @@
//===- PowerPCInstrInfo.td - Describe the PowerPC Instruction Set -*- 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.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
class Format<bits<4> val> {
bits<4> Value = val;
}
// All of the PowerPC instruction formats, plus a pseudo-instruction format:
def Pseudo : Format<0>;
def IForm : Format<1>;
def BForm : Format<2>;
def SCForm : Format<3>;
def DForm : Format<4>;
def XForm : Format<5>;
def XLForm : Format<6>;
def XFXForm : Format<7>;
def XFLForm : Format<8>;
def XOForm : Format<9>;
def AForm : Format<10>;
def MForm : Format<11>;
class PPCInst<string nm, bits<6> opcd, Format f> : Instruction {
let Namespace = "PowerPC";
let Name = nm;
bits<6> Opcode = opcd;
Format Form = f;
bits<4> FormBits = Form.Value;
}
// Pseudo-instructions:
def PHI : PPCInst<"PHI", 0, Pseudo>; // PHI node...
def NOP : PPCInst<"NOP", 0, Pseudo>; // No-op
def ADJCALLSTACKDOWN : PPCInst<"ADJCALLSTACKDOWN", 0, Pseudo>;
def ADJCALLSTACKUP : PPCInst<"ADJCALLSTACKUP", 0, Pseudo>;

View File

@@ -1,49 +0,0 @@
//===- PowerPCJITInfo.h - PowerPC impl. of the JIT interface ----*- 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 PowerPC implementation of the TargetJITInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef POWERPCJITINFO_H
#define POWERPCJITINFO_H
#include "llvm/Target/TargetJITInfo.h"
namespace llvm {
class TargetMachine;
class IntrinsicLowering;
class PowerPCJITInfo : public TargetJITInfo {
TargetMachine &TM;
public:
PowerPCJITInfo(TargetMachine &tm) : TM(tm) {}
/// addPassesToJITCompile - Add passes to the specified pass manager to
/// implement a fast dynamic compiler for this target. Return true if this
/// is not supported for this target.
///
virtual void addPassesToJITCompile(FunctionPassManager &PM);
/// replaceMachineCodeForFunction - Make it so that calling the function
/// whose machine code is at OLD turns into a call to NEW, perhaps by
/// overwriting OLD with a branch to NEW. This is used for self-modifying
/// code.
///
virtual void replaceMachineCodeForFunction(void *Old, void *New);
/// getJITStubForFunction - Create or return a stub for the specified
/// function. This stub acts just like the specified function, except that
/// it allows the "address" of the function to be taken without having to
/// generate code for it.
virtual void *getJITStubForFunction(Function *F, MachineCodeEmitter &MCE);
};
}
#endif

View File

@@ -1,82 +0,0 @@
//===- PowerPCReg.td - Describe the PowerPC Register File -------*- 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.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
class PPCReg : Register {
let Namespace = "PowerPC";
}
// We identify all our registers with a 5-bit ID, for consistency's sake.
// GPR - One of the 32 32-bit general-purpose registers
class GPR<bits<5> num> : PPCReg {
field bits<5> Num = num;
}
// SPR - One of the 32-bit special-purpose registers
class SPR<bits<5> num> : PPCReg {
field bits<5> Num = num;
}
// FPR - One of the 32 64-bit floating-point registers
class FPR<bits<5> num> : PPCReg {
field bits<5> Num = num;
}
// CR - One of the 8 4-bit condition registers
class CR<bits<5> num> : PPCReg {
field bits<5> Num = num;
}
// General-purpose registers
def R0 : GPR< 0>; def R1 : GPR< 1>; def R2 : GPR< 2>; def R3 : GPR< 3>;
def R4 : GPR< 4>; def R5 : GPR< 5>; def R6 : GPR< 6>; def R7 : GPR< 7>;
def R8 : GPR< 8>; def R9 : GPR< 9>; def R10 : GPR<10>; def R11 : GPR<11>;
def R12 : GPR<12>; def R13 : GPR<13>; def R14 : GPR<14>; def R15 : GPR<15>;
def R16 : GPR<16>; def R17 : GPR<17>; def R18 : GPR<18>; def R19 : GPR<19>;
def R20 : GPR<20>; def R21 : GPR<21>; def R22 : GPR<22>; def R23 : GPR<23>;
def R24 : GPR<24>; def R25 : GPR<25>; def R26 : GPR<26>; def R27 : GPR<27>;
def R28 : GPR<28>; def R29 : GPR<29>; def R30 : GPR<30>; def R31 : GPR<31>;
// Floating-point registers
def F0 : FPR< 0>; def F1 : FPR< 1>; def F2 : FPR< 2>; def F3 : FPR< 3>;
def F4 : FPR< 4>; def F5 : FPR< 5>; def F6 : FPR< 6>; def F7 : FPR< 7>;
def F8 : FPR< 8>; def F9 : FPR< 9>; def F10 : FPR<10>; def F11 : FPR<11>;
def F12 : FPR<12>; def F13 : FPR<13>; def F14 : FPR<14>; def F15 : FPR<15>;
def F16 : FPR<16>; def F17 : FPR<17>; def F18 : FPR<18>; def F19 : FPR<19>;
def F20 : FPR<20>; def F21 : FPR<21>; def F22 : FPR<22>; def F23 : FPR<23>;
def F24 : FPR<24>; def F25 : FPR<25>; def F26 : FPR<26>; def F27 : FPR<27>;
def F28 : FPR<28>; def F29 : FPR<29>; def F30 : FPR<30>; def F31 : FPR<31>;
// Condition registers
def CR0 : CR<0>; def CR1 : CR<1>; def CR2 : CR<2>; def CR3 : CR<3>;
def CR4 : CR<4>; def CR5 : CR<5>; def CR6 : CR<6>; def CR7 : CR<7>;
// Floating-point status and control register
def FPSCR : SPR<0>;
// fiXed-point Exception Register? :-)
def XER : SPR<1>;
// Link register
def LR : SPR<2>;
// Count register
def CTR : SPR<3>;
// These are the "time base" registers which are read-only in user mode.
def TBL : SPR<4>;
def TBU : SPR<5>;
/// Register classes: one for floats and another for non-floats.
def GPRC : RegisterClass<i32, 4, [R0, R1, R2, R3, R4, R5, R6, R7,
R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19, R20, R21,
R22, R23, R24, R25, R26, R27, R28, R29, R30, R31]>;
def FPRC : RegisterClass<f64, 8, [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]>;

View File

@@ -1,59 +0,0 @@
//===-- PowerPCTargetMachine.cpp - Define TargetMachine for PowerPC -------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#include "PowerPCTargetMachine.h"
#include "PowerPC.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
using namespace llvm;
// allocatePowerPCTargetMachine - Allocate and return a subclass of
// TargetMachine that implements the PowerPC backend.
//
TargetMachine *llvm::allocatePowerPCTargetMachine(const Module &M,
IntrinsicLowering *IL) {
return new PowerPCTargetMachine(M, IL);
}
/// PowerPCTargetMachine ctor - Create an ILP32 architecture model
///
PowerPCTargetMachine::PowerPCTargetMachine(const Module &M,
IntrinsicLowering *IL)
: TargetMachine("PowerPC", IL, true, 4, 4, 4, 4, 4),
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 4), JITInfo(*this) {
}
/// addPassesToEmitAssembly - Add passes to the specified pass manager
/// to implement a static compiler for this target.
///
bool PowerPCTargetMachine::addPassesToEmitAssembly(PassManager &PM,
std::ostream &Out) {
// <insert instruction selector passes here>
PM.add(createRegisterAllocator());
PM.add(createPrologEpilogCodeInserter());
// <insert assembly code output passes here>
PM.add(createMachineCodeDeleter());
return true; // change to `return false' when this actually works.
}
/// addPassesToJITCompile - Add passes to the specified pass manager to
/// implement a fast dynamic compiler for this target.
///
void PowerPCJITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
// <insert instruction selector passes here>
PM.add(createRegisterAllocator());
PM.add(createPrologEpilogCodeInserter());
}

View File

@@ -1,334 +0,0 @@
//===-- InstSelectSimple.cpp - A simple instruction selector for SparcV8 --===//
//
// 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 simple peephole instruction selector for the V8 target
//
//===----------------------------------------------------------------------===//
#include "SparcV8.h"
#include "SparcV8InstrInfo.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicLowering.h"
#include "llvm/Pass.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/SSARegMap.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/InstVisitor.h"
#include "llvm/Support/CFG.h"
using namespace llvm;
namespace {
struct V8ISel : public FunctionPass, public InstVisitor<V8ISel> {
TargetMachine &TM;
MachineFunction *F; // The function we are compiling into
MachineBasicBlock *BB; // The current MBB we are compiling
std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
// MBBMap - Mapping between LLVM BB -> Machine BB
std::map<const BasicBlock*, MachineBasicBlock*> MBBMap;
V8ISel(TargetMachine &tm) : TM(tm), F(0), BB(0) {}
/// runOnFunction - Top level implementation of instruction selection for
/// the entire function.
///
bool runOnFunction(Function &Fn);
virtual const char *getPassName() const {
return "SparcV8 Simple Instruction Selection";
}
/// visitBasicBlock - This method is called when we are visiting a new basic
/// block. This simply creates a new MachineBasicBlock to emit code into
/// and adds it to the current MachineFunction. Subsequent visit* for
/// instructions will be invoked for all instructions in the basic block.
///
void visitBasicBlock(BasicBlock &LLVM_BB) {
BB = MBBMap[&LLVM_BB];
}
void visitBinaryOperator(BinaryOperator &I);
void visitReturnInst(ReturnInst &RI);
void visitInstruction(Instruction &I) {
std::cerr << "Unhandled instruction: " << I;
abort();
}
/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
/// function, lowering any calls to unknown intrinsic functions into the
/// equivalent LLVM code.
void LowerUnknownIntrinsicFunctionCalls(Function &F);
void visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI);
/// copyConstantToRegister - Output the instructions required to put the
/// specified constant into the specified register.
///
void copyConstantToRegister(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
Constant *C, unsigned R);
/// makeAnotherReg - This method returns the next register number we haven't
/// yet used.
///
/// Long values are handled somewhat specially. They are always allocated
/// as pairs of 32 bit integer values. The register number returned is the
/// lower 32 bits of the long value, and the regNum+1 is the upper 32 bits
/// of the long value.
///
unsigned makeAnotherReg(const Type *Ty) {
assert(dynamic_cast<const SparcV8RegisterInfo*>(TM.getRegisterInfo()) &&
"Current target doesn't have SparcV8 reg info??");
const SparcV8RegisterInfo *MRI =
static_cast<const SparcV8RegisterInfo*>(TM.getRegisterInfo());
if (Ty == Type::LongTy || Ty == Type::ULongTy) {
const TargetRegisterClass *RC = MRI->getRegClassForType(Type::IntTy);
// Create the lower part
F->getSSARegMap()->createVirtualRegister(RC);
// Create the upper part.
return F->getSSARegMap()->createVirtualRegister(RC)-1;
}
// Add the mapping of regnumber => reg class to MachineFunction
const TargetRegisterClass *RC = MRI->getRegClassForType(Ty);
return F->getSSARegMap()->createVirtualRegister(RC);
}
unsigned getReg(Value &V) { return getReg (&V); } // allow refs.
unsigned getReg(Value *V) {
// Just append to the end of the current bb.
MachineBasicBlock::iterator It = BB->end();
return getReg(V, BB, It);
}
unsigned getReg(Value *V, MachineBasicBlock *MBB,
MachineBasicBlock::iterator IPt) {
unsigned &Reg = RegMap[V];
if (Reg == 0) {
Reg = makeAnotherReg(V->getType());
RegMap[V] = Reg;
}
// If this operand is a constant, emit the code to copy the constant into
// the register here...
//
if (Constant *C = dyn_cast<Constant>(V)) {
copyConstantToRegister(MBB, IPt, C, Reg);
RegMap.erase(V); // Assign a new name to this constant if ref'd again
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
// Move the address of the global into the register
unsigned TmpReg = makeAnotherReg(V->getType());
BuildMI (*MBB, IPt, V8::SETHIi, 1, TmpReg).addGlobalAddress (GV);
BuildMI (*MBB, IPt, V8::ORri, 2, Reg).addReg (TmpReg)
.addGlobalAddress (GV);
RegMap.erase(V); // Assign a new name to this address if ref'd again
}
return Reg;
}
};
}
FunctionPass *llvm::createSparcV8SimpleInstructionSelector(TargetMachine &TM) {
return new V8ISel(TM);
}
enum TypeClass {
cByte, cShort, cInt, cLong, cFloat, cDouble
};
static TypeClass getClass (const Type *T) {
switch (T->getPrimitiveID ()) {
case Type::UByteTyID: case Type::SByteTyID: return cByte;
case Type::UShortTyID: case Type::ShortTyID: return cShort;
case Type::UIntTyID: case Type::IntTyID: return cInt;
case Type::ULongTyID: case Type::LongTyID: return cLong;
case Type::FloatTyID: return cFloat;
case Type::DoubleTyID: return cDouble;
default:
assert (0 && "Type of unknown class passed to getClass?");
return cByte;
}
}
/// copyConstantToRegister - Output the instructions required to put the
/// specified constant into the specified register.
///
void V8ISel::copyConstantToRegister(MachineBasicBlock *MBB,
MachineBasicBlock::iterator IP,
Constant *C, unsigned R) {
if (ConstantInt *CI = dyn_cast<ConstantInt> (C)) {
unsigned Class = getClass(C->getType());
switch (Class) {
case cByte:
BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (V8::G0).addImm ((uint8_t) CI->getRawValue ());
return;
case cShort: {
unsigned TmpReg = makeAnotherReg (C->getType ());
BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addImm (((uint16_t) CI->getRawValue ()) >> 10);
BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg).addImm (((uint16_t) CI->getRawValue ()) & 0x03ff);
return;
}
case cInt: {
unsigned TmpReg = makeAnotherReg (C->getType ());
BuildMI (*MBB, IP, V8::SETHIi, 1, TmpReg).addImm (((uint32_t) CI->getRawValue ()) >> 10);
BuildMI (*MBB, IP, V8::ORri, 2, R).addReg (TmpReg).addImm (((uint32_t) CI->getRawValue ()) & 0x03ff);
return;
}
default:
assert (0 && "Can't copy this kind of constant into register yet");
return;
}
}
assert (0 && "Can't copy this kind of constant into register yet");
}
bool V8ISel::runOnFunction(Function &Fn) {
// First pass over the function, lower any unknown intrinsic functions
// with the IntrinsicLowering class.
LowerUnknownIntrinsicFunctionCalls(Fn);
F = &MachineFunction::construct(&Fn, TM);
// Create all of the machine basic blocks for the function...
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
F->getBasicBlockList().push_back(MBBMap[I] = new MachineBasicBlock(I));
BB = &F->front();
// Set up a frame object for the return address. This is used by the
// llvm.returnaddress & llvm.frameaddress intrinisics.
//ReturnAddressIndex = F->getFrameInfo()->CreateFixedObject(4, -4);
// Copy incoming arguments off of the stack and out of fixed registers.
//LoadArgumentsToVirtualRegs(Fn);
// Instruction select everything except PHI nodes
visit(Fn);
// Select the PHI nodes
//SelectPHINodes();
RegMap.clear();
MBBMap.clear();
F = 0;
// We always build a machine code representation for the function
return true;
}
void V8ISel::visitReturnInst(ReturnInst &I) {
if (I.getNumOperands () == 1) {
unsigned RetValReg = getReg (I.getOperand (0));
switch (getClass (I.getOperand (0)->getType ())) {
case cByte:
case cShort:
case cInt:
// Schlep it over into i0 (where it will become o0 after restore).
BuildMI (BB, V8::ORrr, 2, V8::I0).addReg(V8::G0).addReg(RetValReg);
break;
default:
visitInstruction (I);
return;
}
} else if (I.getNumOperands () != 1) {
visitInstruction (I);
}
// Just emit a 'retl' instruction to return.
BuildMI(BB, V8::RETL, 0);
return;
}
void V8ISel::visitBinaryOperator (BinaryOperator &I) {
unsigned DestReg = getReg (I);
unsigned Op0Reg = getReg (I.getOperand (0));
unsigned Op1Reg = getReg (I.getOperand (1));
unsigned ResultReg = makeAnotherReg (I.getType ());
switch (I.getOpcode ()) {
case Instruction::Add:
BuildMI (BB, V8::ADDrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
break;
case Instruction::Sub:
BuildMI (BB, V8::SUBrr, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
break;
case Instruction::Mul: {
unsigned MulOpcode = I.getType ()->isSigned () ? V8::SMULrr : V8::UMULrr;
BuildMI (BB, MulOpcode, 2, ResultReg).addReg (Op0Reg).addReg (Op1Reg);
break;
}
default:
visitInstruction (I);
return;
}
switch (getClass (I.getType ())) {
case cByte:
if (I.getType ()->isSigned ()) { // add byte
BuildMI (BB, V8::ANDri, 2, DestReg).addReg (ResultReg).addZImm (0xff);
} else { // add ubyte
unsigned TmpReg = makeAnotherReg (I.getType ());
BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (24);
BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (24);
}
break;
case cShort:
if (I.getType ()->isSigned ()) { // add short
unsigned TmpReg = makeAnotherReg (I.getType ());
BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16);
BuildMI (BB, V8::SRAri, 2, DestReg).addReg (TmpReg).addZImm (16);
} else { // add ushort
unsigned TmpReg = makeAnotherReg (I.getType ());
BuildMI (BB, V8::SLLri, 2, TmpReg).addReg (ResultReg).addZImm (16);
BuildMI (BB, V8::SRLri, 2, DestReg).addReg (TmpReg).addZImm (16);
}
break;
case cInt:
BuildMI (BB, V8::ORrr, 2, DestReg).addReg (V8::G0).addReg (ResultReg);
break;
default:
visitInstruction (I);
return;
}
}
/// LowerUnknownIntrinsicFunctionCalls - This performs a prepass over the
/// function, lowering any calls to unknown intrinsic functions into the
/// equivalent LLVM code.
void V8ISel::LowerUnknownIntrinsicFunctionCalls(Function &F) {
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; )
if (CallInst *CI = dyn_cast<CallInst>(I++))
if (Function *F = CI->getCalledFunction())
switch (F->getIntrinsicID()) {
case Intrinsic::not_intrinsic: break;
default:
// All other intrinsic calls we must lower.
Instruction *Before = CI->getPrev();
TM.getIntrinsicLowering().LowerIntrinsicCall(CI);
if (Before) { // Move iterator to instruction after call
I = Before; ++I;
} else {
I = BB->begin();
}
}
}
void V8ISel::visitIntrinsicCall(Intrinsic::ID ID, CallInst &CI) {
unsigned TmpReg1, TmpReg2;
switch (ID) {
default: assert(0 && "Intrinsic not supported!");
}
}

View File

@@ -1,46 +0,0 @@
##===- lib/Target/SparcV8/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 = ../../..
LIBRARYNAME = sparcv8
include $(LEVEL)/Makefile.common
TDFILES := $(wildcard $(SourceDir)/*.td) $(SourceDir)/../Target.td
TDFILE := $(SourceDir)/SparcV8.td
# Make sure that tblgen is run, first thing.
$(SourceDepend): SparcV8GenRegisterInfo.h.inc SparcV8GenRegisterNames.inc \
SparcV8GenRegisterInfo.inc SparcV8GenInstrNames.inc \
SparcV8GenInstrInfo.inc SparcV8GenInstrSelector.inc
SparcV8GenRegisterNames.inc:: $(TDFILES) $(TBLGEN)
@echo "Building SparcV8.td register names with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-enums -o $@
SparcV8GenRegisterInfo.h.inc:: $(TDFILES) $(TBLGEN)
@echo "Building SparcV8.td register information header with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-desc-header -o $@
SparcV8GenRegisterInfo.inc:: $(TDFILES) $(TBLGEN)
@echo "Building SparcV8.td register information implementation with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-register-desc -o $@
SparcV8GenInstrNames.inc:: $(TDFILES) $(TBLGEN)
@echo "Building SparcV8.td instruction names with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-enums -o $@
SparcV8GenInstrInfo.inc:: $(TDFILES) $(TBLGEN)
@echo "Building SparcV8.td instruction information with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-desc -o $@
SparcV8GenInstrSelector.inc:: $(TDFILES) $(TBLGEN)
@echo "Building SparcV8.td instruction selector with tblgen"
$(VERB) $(TBLGEN) -I $(BUILD_SRC_DIR) $(TDFILE) -gen-instr-selector -o $@
clean::
$(VERB) rm -f *.inc

View File

@@ -1,9 +0,0 @@
SparcV8 backend skeleton
------------------------
This directory will house a 32-bit SPARC V8 backend employing a expander-based
instruction selector. Watch this space for more news coming soon!
$Date$

View File

@@ -1,40 +0,0 @@
//===-- SparcV8.h - Top-level interface for SparcV8 representation -*- 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 entry points for global functions defined in the LLVM
// SparcV8 back-end.
//
//===----------------------------------------------------------------------===//
#ifndef TARGET_SPARCV8_H
#define TARGET_SPARCV8_H
#include <iosfwd>
namespace llvm {
class FunctionPass;
class TargetMachine;
FunctionPass *createSparcV8SimpleInstructionSelector(TargetMachine &TM);
FunctionPass *createSparcV8CodePrinterPass(std::ostream &OS,
TargetMachine &TM);
} // end namespace llvm;
// Defines symbolic names for SparcV8 registers. This defines a mapping from
// register name to register number.
//
#include "SparcV8GenRegisterNames.inc"
// Defines symbolic names for the SparcV8 instructions.
//
#include "SparcV8GenInstrNames.inc"
#endif

View File

@@ -1,38 +0,0 @@
//===- SparcV8.td - Describe the SparcV8 Target Machine ---------*- 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.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
// Get the target-independent interfaces which we are implementing...
//
include "../Target.td"
//===----------------------------------------------------------------------===//
// Register File Description
//===----------------------------------------------------------------------===//
include "SparcV8RegisterInfo.td"
include "SparcV8InstrInfo.td"
def SparcV8InstrInfo : InstrInfo {
let PHIInst = PHI;
}
def SparcV8 : Target {
// Pointers are 32-bits in size.
let PointerType = i32;
// According to the Mach-O Runtime ABI, these regs are nonvolatile across
// calls:
let CalleeSavedRegisters = [];
// Pull in Instruction Info:
let InstructionSet = SparcV8InstrInfo;
}

View File

@@ -1,529 +0,0 @@
//===-- SparcV8AsmPrinter.cpp - SparcV8 LLVM assembly writer --------------===//
//
// 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 printer that converts from our internal representation
// of machine-dependent LLVM code to GAS-format Sparc V8 assembly language.
//
//===----------------------------------------------------------------------===//
#include "SparcV8.h"
#include "SparcV8InstrInfo.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Mangler.h"
#include "Support/Statistic.h"
#include "Support/StringExtras.h"
#include "Support/CommandLine.h"
#include <cctype>
using namespace llvm;
namespace {
Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
struct V8Printer : public MachineFunctionPass {
/// Output stream on which we're printing assembly code.
///
std::ostream &O;
/// Target machine description which we query for reg. names, data
/// layout, etc.
///
TargetMachine &TM;
/// Name-mangler for global names.
///
Mangler *Mang;
V8Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { }
/// We name each basic block in a Function with a unique number, so
/// that we can consistently refer to them later. This is cleared
/// at the beginning of each call to runOnMachineFunction().
///
typedef std::map<const Value *, unsigned> ValueMapTy;
ValueMapTy NumberForBB;
/// Cache of mangled name for current function. This is
/// recalculated at the beginning of each call to
/// runOnMachineFunction().
///
std::string CurrentFnName;
virtual const char *getPassName() const {
return "SparcV8 Assembly Printer";
}
void emitConstantValueOnly(const Constant *CV);
void emitGlobalConstant(const Constant *CV);
void printConstantPool(MachineConstantPool *MCP);
void printOperand(const MachineOperand &MI);
void printMachineInstruction(const MachineInstr *MI);
bool runOnMachineFunction(MachineFunction &F);
bool doInitialization(Module &M);
bool doFinalization(Module &M);
};
} // end of anonymous namespace
/// createSparcV8CodePrinterPass - Returns a pass that prints the SparcV8
/// assembly code for a MachineFunction to the given output stream,
/// using the given target machine description. This should work
/// regardless of whether the function is in SSA form.
///
FunctionPass *llvm::createSparcV8CodePrinterPass (std::ostream &o,
TargetMachine &tm) {
return new V8Printer(o, tm);
}
/// toOctal - Convert the low order bits of X into an octal digit.
///
static inline char toOctal(int X) {
return (X&7)+'0';
}
/// getAsCString - Return the specified array as a C compatible
/// string, only if the predicate isStringCompatible is true.
///
static void printAsCString(std::ostream &O, const ConstantArray *CVA) {
assert(CVA->isString() && "Array is not string compatible!");
O << "\"";
for (unsigned i = 0; i != CVA->getNumOperands(); ++i) {
unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue();
if (C == '"') {
O << "\\\"";
} else if (C == '\\') {
O << "\\\\";
} else if (isprint(C)) {
O << C;
} else {
switch(C) {
case '\b': O << "\\b"; break;
case '\f': O << "\\f"; break;
case '\n': O << "\\n"; break;
case '\r': O << "\\r"; break;
case '\t': O << "\\t"; break;
default:
O << '\\';
O << toOctal(C >> 6);
O << toOctal(C >> 3);
O << toOctal(C >> 0);
break;
}
}
}
O << "\"";
}
// Print out the specified constant, without a storage class. Only the
// constants valid in constant expressions can occur here.
void V8Printer::emitConstantValueOnly(const Constant *CV) {
if (CV->isNullValue())
O << "0";
else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) {
assert(CB == ConstantBool::True);
O << "1";
} else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV))
if (((CI->getValue() << 32) >> 32) == CI->getValue())
O << CI->getValue();
else
O << (unsigned long long)CI->getValue();
else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV))
O << CI->getValue();
else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV))
// This is a constant address for a global variable or function. Use the
// name of the variable or function as the address value.
O << Mang->getValueName(CPR->getValue());
else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
const TargetData &TD = TM.getTargetData();
switch(CE->getOpcode()) {
case Instruction::GetElementPtr: {
// generate a symbolic expression for the byte address
const Constant *ptrVal = CE->getOperand(0);
std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end());
if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) {
O << "(";
emitConstantValueOnly(ptrVal);
O << ") + " << Offset;
} else {
emitConstantValueOnly(ptrVal);
}
break;
}
case Instruction::Cast: {
// Support only non-converting or widening casts for now, that is, ones
// that do not involve a change in value. This assertion is really gross,
// and may not even be a complete check.
Constant *Op = CE->getOperand(0);
const Type *OpTy = Op->getType(), *Ty = CE->getType();
// Pointers on ILP32 machines can be losslessly converted back and
// forth into 32-bit or wider integers, regardless of signedness.
assert(((isa<PointerType>(OpTy)
&& (Ty == Type::LongTy || Ty == Type::ULongTy
|| Ty == Type::IntTy || Ty == Type::UIntTy))
|| (isa<PointerType>(Ty)
&& (OpTy == Type::LongTy || OpTy == Type::ULongTy
|| OpTy == Type::IntTy || OpTy == Type::UIntTy))
|| (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy))
&& OpTy->isLosslesslyConvertibleTo(Ty))))
&& "FIXME: Don't yet support this kind of constant cast expr");
O << "(";
emitConstantValueOnly(Op);
O << ")";
break;
}
case Instruction::Add:
O << "(";
emitConstantValueOnly(CE->getOperand(0));
O << ") + (";
emitConstantValueOnly(CE->getOperand(1));
O << ")";
break;
default:
assert(0 && "Unsupported operator!");
}
} else {
assert(0 && "Unknown constant value!");
}
}
// Print a constant value or values, with the appropriate storage class as a
// prefix.
void V8Printer::emitGlobalConstant(const Constant *CV) {
const TargetData &TD = TM.getTargetData();
if (CV->isNullValue()) {
O << "\t.zero\t " << TD.getTypeSize(CV->getType()) << "\n";
return;
} else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
if (CVA->isString()) {
O << "\t.ascii\t";
printAsCString(O, CVA);
O << "\n";
} else { // Not a string. Print the values in successive locations
const std::vector<Use> &constValues = CVA->getValues();
for (unsigned i=0; i < constValues.size(); i++)
emitGlobalConstant(cast<Constant>(constValues[i].get()));
}
return;
} else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
// Print the fields in successive locations. Pad to align if needed!
const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType());
const std::vector<Use>& constValues = CVS->getValues();
unsigned sizeSoFar = 0;
for (unsigned i=0, N = constValues.size(); i < N; i++) {
const Constant* field = cast<Constant>(constValues[i].get());
// Check if padding is needed and insert one or more 0s.
unsigned fieldSize = TD.getTypeSize(field->getType());
unsigned padSize = ((i == N-1? cvsLayout->StructSize
: cvsLayout->MemberOffsets[i+1])
- cvsLayout->MemberOffsets[i]) - fieldSize;
sizeSoFar += fieldSize + padSize;
// Now print the actual field value
emitGlobalConstant(field);
// Insert the field padding unless it's zero bytes...
if (padSize)
O << "\t.zero\t " << padSize << "\n";
}
assert(sizeSoFar == cvsLayout->StructSize &&
"Layout of constant struct may be incorrect!");
return;
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
// FP Constants are printed as integer constants to avoid losing
// precision...
double Val = CFP->getValue();
switch (CFP->getType()->getPrimitiveID()) {
default: assert(0 && "Unknown floating point type!");
case Type::FloatTyID: {
union FU { // Abide by C TBAA rules
float FVal;
unsigned UVal;
} U;
U.FVal = Val;
O << ".long\t" << U.UVal << "\t! float " << Val << "\n";
return;
}
case Type::DoubleTyID: {
union DU { // Abide by C TBAA rules
double FVal;
uint64_t UVal;
} U;
U.FVal = Val;
O << ".quad\t" << U.UVal << "\t! double " << Val << "\n";
return;
}
}
}
const Type *type = CV->getType();
O << "\t";
switch (type->getPrimitiveID()) {
case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID:
O << ".byte";
break;
case Type::UShortTyID: case Type::ShortTyID:
O << ".word";
break;
case Type::FloatTyID: case Type::PointerTyID:
case Type::UIntTyID: case Type::IntTyID:
O << ".long";
break;
case Type::DoubleTyID:
case Type::ULongTyID: case Type::LongTyID:
O << ".quad";
break;
default:
assert (0 && "Can't handle printing this type of thing");
break;
}
O << "\t";
emitConstantValueOnly(CV);
O << "\n";
}
/// printConstantPool - Print to the current output stream assembly
/// representations of the constants in the constant pool MCP. This is
/// used to print out constants which have been "spilled to memory" by
/// the code generator.
///
void V8Printer::printConstantPool(MachineConstantPool *MCP) {
const std::vector<Constant*> &CP = MCP->getConstants();
const TargetData &TD = TM.getTargetData();
if (CP.empty()) return;
for (unsigned i = 0, e = CP.size(); i != e; ++i) {
O << "\t.section .rodata\n";
O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType())
<< "\n";
O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t!"
<< *CP[i] << "\n";
emitGlobalConstant(CP[i]);
}
}
/// runOnMachineFunction - This uses the printMachineInstruction()
/// method to print assembly for each instruction.
///
bool V8Printer::runOnMachineFunction(MachineFunction &MF) {
// BBNumber is used here so that a given Printer will never give two
// BBs the same name. (If you have a better way, please let me know!)
static unsigned BBNumber = 0;
O << "\n\n";
// What's my mangled name?
CurrentFnName = Mang->getValueName(MF.getFunction());
// Print out constants referenced by the function
printConstantPool(MF.getConstantPool());
// Print out labels for the function.
O << "\t.text\n";
O << "\t.align 16\n";
O << "\t.globl\t" << CurrentFnName << "\n";
O << "\t.type\t" << CurrentFnName << ", #function\n";
O << CurrentFnName << ":\n";
// Number each basic block so that we can consistently refer to them
// in PC-relative references.
NumberForBB.clear();
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
NumberForBB[I->getBasicBlock()] = BBNumber++;
}
// Print out code for the function.
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
// Print a label for the basic block.
O << ".LBB" << NumberForBB[I->getBasicBlock()] << ":\t! "
<< I->getBasicBlock()->getName() << "\n";
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
// Print the assembly for the instruction.
O << "\t";
printMachineInstruction(II);
}
}
// We didn't modify anything.
return false;
}
std::string LowercaseString (const std::string &S) {
std::string result (S);
for (unsigned i = 0; i < S.length(); ++i)
if (isupper (result[i]))
result[i] = tolower(result[i]);
return result;
}
void V8Printer::printOperand(const MachineOperand &MO) {
const MRegisterInfo &RI = *TM.getRegisterInfo();
switch (MO.getType()) {
case MachineOperand::MO_VirtualRegister:
if (Value *V = MO.getVRegValueOrNull()) {
O << "<" << V->getName() << ">";
return;
}
// FALLTHROUGH
case MachineOperand::MO_MachineRegister:
if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
O << "%" << LowercaseString (RI.get(MO.getReg()).Name);
else
O << "%reg" << MO.getReg();
return;
case MachineOperand::MO_SignExtendedImmed:
case MachineOperand::MO_UnextendedImmed:
O << (int)MO.getImmedValue();
return;
case MachineOperand::MO_PCRelativeDisp: {
ValueMapTy::const_iterator i = NumberForBB.find(MO.getVRegValue());
assert (i != NumberForBB.end()
&& "Could not find a BB in the NumberForBB map!");
O << ".LBB" << i->second << " ! PC rel: " << MO.getVRegValue()->getName();
return;
}
case MachineOperand::MO_GlobalAddress:
O << Mang->getValueName(MO.getGlobal());
return;
case MachineOperand::MO_ExternalSymbol:
O << MO.getSymbolName();
return;
default:
O << "<unknown operand type>"; return;
}
}
/// printMachineInstruction -- Print out a single SparcV8 LLVM instruction
/// MI in GAS syntax to the current output stream.
///
void V8Printer::printMachineInstruction(const MachineInstr *MI) {
unsigned Opcode = MI->getOpcode();
const TargetInstrInfo &TII = TM.getInstrInfo();
const TargetInstrDescriptor &Desc = TII.get(Opcode);
O << Desc.Name << " ";
// print non-immediate, non-register-def operands
// then print immediate operands
// then print register-def operands.
std::vector<MachineOperand> print_order;
for (unsigned i = 0; i < MI->getNumOperands (); ++i)
if (!(MI->getOperand (i).isImmediate ()
|| (MI->getOperand (i).isRegister ()
&& MI->getOperand (i).isDef ())))
print_order.push_back (MI->getOperand (i));
for (unsigned i = 0; i < MI->getNumOperands (); ++i)
if (MI->getOperand (i).isImmediate ())
print_order.push_back (MI->getOperand (i));
for (unsigned i = 0; i < MI->getNumOperands (); ++i)
if (MI->getOperand (i).isRegister () && MI->getOperand (i).isDef ())
print_order.push_back (MI->getOperand (i));
for (unsigned i = 0, e = print_order.size (); i != e; ++i) {
printOperand (print_order[i]);
if (i != (print_order.size () - 1))
O << ", ";
}
O << "\n";
}
bool V8Printer::doInitialization(Module &M) {
Mang = new Mangler(M);
return false; // success
}
// SwitchSection - Switch to the specified section of the executable if we are
// not already in it!
//
static void SwitchSection(std::ostream &OS, std::string &CurSection,
const char *NewSection) {
if (CurSection != NewSection) {
CurSection = NewSection;
if (!CurSection.empty())
OS << "\t" << NewSection << "\n";
}
}
bool V8Printer::doFinalization(Module &M) {
const TargetData &TD = TM.getTargetData();
std::string CurSection;
// Print out module-level global variables here.
for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I)
if (I->hasInitializer()) { // External global require no code
O << "\n\n";
std::string name = Mang->getValueName(I);
Constant *C = I->getInitializer();
unsigned Size = TD.getTypeSize(C->getType());
unsigned Align = TD.getTypeAlignment(C->getType());
if (C->isNullValue() &&
(I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
I->hasWeakLinkage() /* FIXME: Verify correct */)) {
SwitchSection(O, CurSection, ".data");
if (I->hasInternalLinkage())
O << "\t.local " << name << "\n";
O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
<< "," << (unsigned)TD.getTypeAlignment(C->getType());
O << "\t\t! ";
WriteAsOperand(O, I, true, true, &M);
O << "\n";
} else {
switch (I->getLinkage()) {
case GlobalValue::LinkOnceLinkage:
case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak.
// Nonnull linkonce -> weak
O << "\t.weak " << name << "\n";
SwitchSection(O, CurSection, "");
O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
break;
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
case GlobalValue::ExternalLinkage:
// If external or appending, declare as a global symbol
O << "\t.globl " << name << "\n";
// FALL THROUGH
case GlobalValue::InternalLinkage:
if (C->isNullValue())
SwitchSection(O, CurSection, ".bss");
else
SwitchSection(O, CurSection, ".data");
break;
}
O << "\t.align " << Align << "\n";
O << "\t.type " << name << ",#object\n";
O << "\t.size " << name << "," << Size << "\n";
O << name << ":\t\t\t\t! ";
WriteAsOperand(O, I, true, true, &M);
O << " = ";
WriteAsOperand(O, C, false, false, &M);
O << "\n";
emitGlobalConstant(C);
}
}
delete Mang;
return false; // success
}

View File

@@ -1,43 +0,0 @@
//===-- SparcV8CodeEmitter.cpp - JIT Code Emitter for SparcV8 -----*- 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.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#include "SparcV8TargetMachine.h"
namespace llvm {
/// addPassesToEmitMachineCode - Add passes to the specified pass manager to get
/// machine code emitted. This uses a MachineCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions. This method should returns true if machine code emission is
/// not supported.
///
bool SparcV8TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
MachineCodeEmitter &MCE) {
return true;
// It should go something like this:
// PM.add(new Emitter(MCE)); // Machine code emitter pass for SparcV8
// Delete machine code for this function after emitting it:
// PM.add(createMachineCodeDeleter());
}
void *SparcV8JITInfo::getJITStubForFunction(Function *F,
MachineCodeEmitter &MCE) {
assert (0 && "SparcV8JITInfo::getJITStubForFunction not implemented");
return 0;
}
void SparcV8JITInfo::replaceMachineCodeForFunction (void *Old, void *New) {
assert (0 && "SparcV8JITInfo::replaceMachineCodeForFunction not implemented");
}
} // end llvm namespace

View File

@@ -1,22 +0,0 @@
//===- SparcV8InstrInfo.cpp - SparcV8 Instruction Information ---*- 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 SparcV8 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#include "SparcV8InstrInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "SparcV8GenInstrInfo.inc"
using namespace llvm;
SparcV8InstrInfo::SparcV8InstrInfo()
: TargetInstrInfo(SparcV8Insts, sizeof(SparcV8Insts)/sizeof(SparcV8Insts[0])){
}

View File

@@ -1,36 +0,0 @@
//===- SparcV8InstrInfo.h - SparcV8 Instruction Information -----*- 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 SparcV8 implementation of the TargetInstrInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef SPARCV8INSTRUCTIONINFO_H
#define SPARCV8INSTRUCTIONINFO_H
#include "llvm/Target/TargetInstrInfo.h"
#include "SparcV8RegisterInfo.h"
namespace llvm {
class SparcV8InstrInfo : public TargetInstrInfo {
const SparcV8RegisterInfo RI;
public:
SparcV8InstrInfo();
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
/// such, whenever a client has an instance of instruction info, it should
/// always be able to get register info as well (through this method).
///
virtual const MRegisterInfo &getRegisterInfo() const { return RI; }
};
}
#endif

View File

@@ -1,97 +0,0 @@
//===- SparcV8Instrs.td - Target Description for SparcV8 Target -----------===//
//
// 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 describes the SparcV8 instructions in TableGen format.
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// Instruction format superclass
//===----------------------------------------------------------------------===//
class InstV8 : Instruction { // SparcV8 instruction baseline
field bits<32> Inst;
let Namespace = "V8";
bits<2> op;
let Inst{31-30} = op; // Top two bits are the 'op' field
// Bit attributes specific to SparcV8 instructions
bit isPasi = 0; // Does this instruction affect an alternate addr space?
bit isPrivileged = 0; // Is this a privileged instruction?
}
include "SparcV8InstrInfo_F2.td"
include "SparcV8InstrInfo_F3.td"
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
// Pseudo instructions.
def PHI : InstV8 {
let Name = "PHI";
}
def ADJCALLSTACKDOWN : InstV8 {
let Name = "ADJCALLSTACKDOWN";
}
def ADJCALLSTACKUP : InstV8 {
let Name = "ADJCALLSTACKUP";
}
// Section A.3 - Synthetic Instructions, p. 85
let isReturn = 1, isTerminator = 1, simm13 = 8 in
def RET : F3_2<2, 0b111000, "ret">;
let isReturn = 1, isTerminator = 1, simm13 = 8 in
def RETL : F3_2<2, 0b111000, "retl">;
// Section B.9 - SETHI Instruction, p. 104
def SETHIi: F2_1<0b100, "sethi">;
// Section B.11 - Logical Instructions, p. 106
def ANDri : F3_2<2, 0b000001, "and">;
def ORrr : F3_1<2, 0b000010, "or">;
def ORri : F3_2<2, 0b000010, "or">;
// Section B.12 - Shift Instructions, p. 107
def SLLri : F3_1<2, 0b100101, "sll">;
def SRLri : F3_1<2, 0b100110, "srl">;
def SRAri : F3_1<2, 0b100111, "sra">;
// Section B.13 - Add Instructions, p. 108
def ADDrr : F3_1<2, 0b000000, "add">;
// Section B.15 - Subtract Instructions, p. 110
def SUBrr : F3_1<2, 0b000100, "sub">;
// Section B.18 - Multiply Instructions, p. 113
def UMULrr : F3_1<2, 0b001010, "umul">;
def SMULrr : F3_1<2, 0b001011, "smul">;
// Section B.20 - SAVE and RESTORE, p. 117
def SAVErr : F3_1<2, 0b111100, "save">; // save r, r, r
def SAVEri : F3_2<2, 0b111100, "save">; // save r, i, r
def RESTORErr : F3_1<2, 0b111101, "restore">; // restore r, r, r
def RESTOREri : F3_2<2, 0b111101, "restore">; // restore r, i, r
// Section B.24 - Call and Link, p. 125
// This is the only Format 1 instruction
def CALL : InstV8 {
bits<30> disp;
let op = 1;
let Inst{29-0} = disp;
let Name = "call";
let isCall = 1;
}
// Section B.25 - Jump and Link, p. 126
def JMPLrr : F3_1<2, 0b111000, "jmpl">; // jmpl [rs1+rs2], rd
def JMPLri : F3_2<2, 0b111000, "jmpl">; // jmpl [rs1+imm], rd

View File

@@ -1,44 +0,0 @@
//===- SparcV8Instrs_F2.td - Format 2 instructions: SparcV8 Target --------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Format #2 instruction classes in the SparcV8
//
//===----------------------------------------------------------------------===//
class F2 : InstV8 { // Format 2 instructions
bits<3> op2;
bits<22> imm22;
let op = 0; // op = 0
let Inst{24-22} = op2;
let Inst{21-0} = imm22;
}
// Specific F2 classes: SparcV8 manual, page 44
//
class F2_1<bits<3> op2Val, string name> : F2 {
bits<5> rd;
bits<22> imm;
let op2 = op2Val;
let Name = name;
let Inst{29-25} = rd;
}
class F2_2<bits<4> condVal, bits<3> op2Val, string name> : F2 {
bits<4> cond;
bit annul = 0; // currently unused
let cond = condVal;
let op2 = op2Val;
let Name = name;
let Inst{29} = annul;
let Inst{28-25} = cond;
}

View File

@@ -1,62 +0,0 @@
//===- SparcV8Instrs_F3.td - Format 3 Instructions: SparcV8 Target --------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
// Format #3 instruction classes in the SparcV8
//
//===----------------------------------------------------------------------===//
class F3 : InstV8 {
bits<5> rd;
bits<6> op3;
bits<5> rs1;
let op{1} = 1; // Op = 2 or 3
let Inst{29-25} = rd;
let Inst{24-19} = op3;
let Inst{18-14} = rs1;
}
// Specific F3 classes: SparcV8 manual, page 44
//
class F3_1<bits<2> opVal, bits<6> op3val, string name> : F3 {
bits<8> asi;
bits<5> rs2;
let op = opVal;
let op3 = op3val;
let Name = name;
let Inst{13} = 0; // i field = 0
let Inst{12-5} = asi; // address space identifier
let Inst{4-0} = rs2;
}
class F3_2<bits<2> opVal, bits<6> op3val, string name> : F3 {
bits<13> simm13;
let op = opVal;
let op3 = op3val;
let Name = name;
let Inst{13} = 1; // i field = 1
let Inst{12-0} = simm13;
}
/*
class F3_3<bits<2> opVal, bits<6> op3val, bits<9> opfVal, string name>
: F3_rs1rs2 {
bits<5> rs2;
let op = opVal;
let op3 = op3val;
let Name = name;
let Inst{13-5} = opfVal;
let Inst{4-0} = rs2;
}
*/

View File

@@ -1,49 +0,0 @@
//===- SparcV8JITInfo.h - SparcV8 impl. of the JIT interface ----*- 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 SparcV8 implementation of the TargetJITInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef SPARCV8JITINFO_H
#define SPARCV8JITINFO_H
#include "llvm/Target/TargetJITInfo.h"
namespace llvm {
class TargetMachine;
class IntrinsicLowering;
class SparcV8JITInfo : public TargetJITInfo {
TargetMachine &TM;
public:
SparcV8JITInfo(TargetMachine &tm) : TM(tm) {}
/// addPassesToJITCompile - Add passes to the specified pass manager to
/// implement a fast dynamic compiler for this target. Return true if this
/// is not supported for this target.
///
virtual void addPassesToJITCompile(FunctionPassManager &PM);
/// replaceMachineCodeForFunction - Make it so that calling the function
/// whose machine code is at OLD turns into a call to NEW, perhaps by
/// overwriting OLD with a branch to NEW. This is used for self-modifying
/// code.
///
virtual void replaceMachineCodeForFunction(void *Old, void *New);
/// getJITStubForFunction - Create or return a stub for the specified
/// function. This stub acts just like the specified function, except that
/// it allows the "address" of the function to be taken without having to
/// generate code for it.
virtual void *getJITStubForFunction(Function *F, MachineCodeEmitter &MCE);
};
}
#endif

View File

@@ -1,106 +0,0 @@
//===- SparcV8RegisterInfo.cpp - SparcV8 Register Information ---*- 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 SparcV8 implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#include "SparcV8.h"
#include "SparcV8RegisterInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Type.h"
#include "Support/STLExtras.h"
using namespace llvm;
SparcV8RegisterInfo::SparcV8RegisterInfo()
: SparcV8GenRegisterInfo(V8::ADJCALLSTACKDOWN,
V8::ADJCALLSTACKUP) {}
int SparcV8RegisterInfo::storeRegToStackSlot(
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned SrcReg, int FrameIdx,
const TargetRegisterClass *RC) const
{
abort();
return -1;
}
int SparcV8RegisterInfo::loadRegFromStackSlot(
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned DestReg, int FrameIdx,
const TargetRegisterClass *RC) const
{
abort();
return -1;
}
int SparcV8RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *RC) const {
abort();
return -1;
}
void SparcV8RegisterInfo::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
abort();
}
void
SparcV8RegisterInfo::eliminateFrameIndex(MachineFunction &MF,
MachineBasicBlock::iterator II) const {
abort();
}
void SparcV8RegisterInfo::
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {}
void SparcV8RegisterInfo::emitPrologue(MachineFunction &MF) const {
MachineBasicBlock &MBB = MF.front();
// Eventually this should emit the correct save instruction based on the
// number of bytes in the frame. For now we just hardcode it.
BuildMI(MBB, MBB.begin(), V8::SAVEri, 2, V8::SP).addImm(-112).addReg(V8::SP);
}
void SparcV8RegisterInfo::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
MachineBasicBlock::iterator MBBI = prior(MBB.end());
assert(MBBI->getOpcode() == V8::RETL &&
"Can only put epilog before 'retl' instruction!");
BuildMI(MBB, MBBI, V8::RESTORErr, 2, V8::G0).addReg(V8::G0).addReg(V8::G0);
}
#include "SparcV8GenRegisterInfo.inc"
const TargetRegisterClass*
SparcV8RegisterInfo::getRegClassForType(const Type* Ty) const {
switch (Ty->getPrimitiveID()) {
case Type::FloatTyID: return &FPRegsInstance;
case Type::DoubleTyID: return &DFPRegsInstance;
case Type::LongTyID:
case Type::ULongTyID: assert(0 && "Long values can't fit in registers!");
default: assert(0 && "Invalid type to getClass!");
case Type::BoolTyID:
case Type::SByteTyID:
case Type::UByteTyID:
case Type::ShortTyID:
case Type::UShortTyID:
case Type::IntTyID:
case Type::UIntTyID:
case Type::PointerTyID: return &IntRegsInstance;
}
}

View File

@@ -1,58 +0,0 @@
//===- SparcV8RegisterInfo.h - SparcV8 Register Information Impl -*- 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 SparcV8 implementation of the MRegisterInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef SPARCV8REGISTERINFO_H
#define SPARCV8REGISTERINFO_H
#include "llvm/Target/MRegisterInfo.h"
#include "SparcV8GenRegisterInfo.h.inc"
namespace llvm {
class Type;
struct SparcV8RegisterInfo : public SparcV8GenRegisterInfo {
SparcV8RegisterInfo();
const TargetRegisterClass* getRegClassForType(const Type* Ty) const;
/// Code Generation virtual methods...
int storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned SrcReg, int FrameIndex,
const TargetRegisterClass *RC) const;
int loadRegFromStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned DestReg, int FrameIndex,
const TargetRegisterClass *RC) const;
int copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
unsigned DestReg, unsigned SrcReg,
const TargetRegisterClass *RC) const;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
void eliminateFrameIndex(MachineFunction &MF,
MachineBasicBlock::iterator II) const;
void processFunctionBeforeFrameFinalized(MachineFunction &MF) const;
void emitPrologue(MachineFunction &MF) const;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
};
} // end namespace llvm
#endif

View File

@@ -1,101 +0,0 @@
//===- SparcV8Reg.td - Describe the SparcV8 Register File -------*- 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.
//
//===----------------------------------------------------------------------===//
//
// Declarations that describe the SparcV8 register file
//
//===----------------------------------------------------------------------===//
// Registers are identified with 5-bit ID numbers.
// Ri - 32-bit integer registers
class Ri<bits<5> num> : Register {
field bits<5> Num = num;
}
// Rf - 32-bit floating-point registers
class Rf<bits<5> num> : Register {
field bits<5> Num = num;
}
// Rd - Slots in the FP register file for 64-bit floating-point values.
class Rd<bits<5> num> : Register {
field bits<5> Num = num;
}
let Namespace = "V8" in {
def G0 : Ri< 0>; def G1 : Ri< 1>; def G2 : Ri< 2>; def G3 : Ri< 3>;
def G4 : Ri< 4>; def G5 : Ri< 5>; def G6 : Ri< 6>; def G7 : Ri< 7>;
def O0 : Ri< 8>; def O1 : Ri< 9>; def O2 : Ri<10>; def O3 : Ri<11>;
def O4 : Ri<12>; def O5 : Ri<13>; def O6 : Ri<14>; def O7 : Ri<15>;
def L0 : Ri<16>; def L1 : Ri<17>; def L2 : Ri<18>; def L3 : Ri<19>;
def L4 : Ri<20>; def L5 : Ri<21>; def L6 : Ri<22>; def L7 : Ri<23>;
def I0 : Ri<24>; def I1 : Ri<25>; def I2 : Ri<26>; def I3 : Ri<27>;
def I4 : Ri<28>; def I5 : Ri<29>; def I6 : Ri<30>; def I7 : Ri<31>;
// Standard register aliases.
def SP : Ri<14>; def FP : Ri<30>;
// Floating-point registers:
def F0 : Rf< 0>; def F1 : Rf< 1>; def F2 : Rf< 2>; def F3 : Rf< 3>;
def F4 : Rf< 4>; def F5 : Rf< 5>; def F6 : Rf< 6>; def F7 : Rf< 7>;
def F8 : Rf< 8>; def F9 : Rf< 9>; def F10 : Rf<10>; def F11 : Rf<11>;
def F12 : Rf<12>; def F13 : Rf<13>; def F14 : Rf<14>; def F15 : Rf<15>;
def F16 : Rf<16>; def F17 : Rf<17>; def F18 : Rf<18>; def F19 : Rf<19>;
def F20 : Rf<20>; def F21 : Rf<21>; def F22 : Rf<22>; def F23 : Rf<23>;
def F24 : Rf<24>; def F25 : Rf<25>; def F26 : Rf<26>; def F27 : Rf<27>;
def F28 : Rf<28>; def F29 : Rf<29>; def F30 : Rf<30>; def F31 : Rf<31>;
// Aliases of the F* registers used to hold 64-bit fp values (doubles).
def D0 : Rd< 0>; def D1 : Rd< 2>; def D2 : Rd< 4>; def D3 : Rd< 6>;
def D4 : Rd< 8>; def D5 : Rd<10>; def D6 : Rd<12>; def D7 : Rd<14>;
def D8 : Rd<16>; def D9 : Rd<18>; def D10 : Rd<20>; def D11 : Rd<22>;
def D12 : Rd<24>; def D13 : Rd<26>; def D14 : Rd<28>; def D15 : Rd<30>;
}
// Register classes.
//
// FIXME: the register order should be defined in terms of the preferred
// allocation order...
//
def IntRegs : RegisterClass<i32, 8, [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,
// Non-allocatable regs
O6, I6, I7, G0]> {
let Methods = [{
iterator allocation_order_end(MachineFunction &MF) const {
return end()-4; // Don't allocate special registers
}
}];
}
def FPRegs : RegisterClass<f32, 4, [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]>;
def DFPRegs : RegisterClass<f64, 8, [D0, D1, D2, D3, D4, D5, D6, D7,
D8, D9, D10, D11, D12, D13, D14, D15]>;
// Tell the register file generator that the double-fp pseudo-registers
// alias the registers used for single-fp values.
def : RegisterAliases<D0, [F0, F1]>;
def : RegisterAliases<D1, [F2, F3]>;
def : RegisterAliases<D2, [F4, F5]>;
def : RegisterAliases<D3, [F6, F7]>;
def : RegisterAliases<D4, [F8, F9]>;
def : RegisterAliases<D5, [F10, F11]>;
def : RegisterAliases<D6, [F12, F13]>;
def : RegisterAliases<D7, [F14, F15]>;
def : RegisterAliases<D8, [F16, F17]>;
def : RegisterAliases<D9, [F18, F19]>;
def : RegisterAliases<D10, [F20, F21]>;
def : RegisterAliases<D11, [F22, F23]>;
def : RegisterAliases<D12, [F24, F25]>;
def : RegisterAliases<D13, [F26, F27]>;
def : RegisterAliases<D14, [F28, F29]>;
def : RegisterAliases<D15, [F30, F31]>;

View File

@@ -1,72 +0,0 @@
//===-- SparcV8TargetMachine.cpp - Define TargetMachine for SparcV8 -------===//
//
// 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.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
#include "SparcV8TargetMachine.h"
#include "SparcV8.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Target/TargetMachineImpls.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
using namespace llvm;
// allocateSparcV8TargetMachine - Allocate and return a subclass of
// TargetMachine that implements the SparcV8 backend.
//
TargetMachine *llvm::allocateSparcV8TargetMachine(const Module &M,
IntrinsicLowering *IL) {
return new SparcV8TargetMachine(M, IL);
}
/// SparcV8TargetMachine ctor - Create an ILP32 architecture model
///
SparcV8TargetMachine::SparcV8TargetMachine(const Module &M,
IntrinsicLowering *IL)
: TargetMachine("SparcV8", IL, true, 4, 4, 4, 4, 4),
FrameInfo(TargetFrameInfo::StackGrowsDown, 8, 4), JITInfo(*this) {
}
/// addPassesToEmitAssembly - Add passes to the specified pass manager
/// to implement a static compiler for this target.
///
bool SparcV8TargetMachine::addPassesToEmitAssembly(PassManager &PM,
std::ostream &Out) {
PM.add(createSparcV8SimpleInstructionSelector(*this));
// Print machine instructions as they were initially generated.
if (PrintMachineCode)
PM.add(createMachineFunctionPrinterPass(&std::cerr));
PM.add(createRegisterAllocator());
PM.add(createPrologEpilogCodeInserter());
// Print machine instructions after register allocation and prolog/epilog
// insertion.
if (PrintMachineCode)
PM.add(createMachineFunctionPrinterPass(&std::cerr));
// Output assembly language.
PM.add(createSparcV8CodePrinterPass(Out, *this));
// Delete the MachineInstrs we generated, since they're no longer needed.
PM.add(createMachineCodeDeleter());
return false;
}
/// addPassesToJITCompile - Add passes to the specified pass manager to
/// implement a fast dynamic compiler for this target.
///
void SparcV8JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
// <insert instruction selector passes here>
PM.add(createRegisterAllocator());
PM.add(createPrologEpilogCodeInserter());
}

View File

@@ -1,60 +0,0 @@
//===-- SparcV8TargetMachine.h - Define TargetMachine for SparcV8 -*- 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 declares the SparcV8 specific subclass of TargetMachine.
//
//===----------------------------------------------------------------------===//
#ifndef SPARCV8TARGETMACHINE_H
#define SPARCV8TARGETMACHINE_H
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/PassManager.h"
#include "SparcV8InstrInfo.h"
#include "SparcV8JITInfo.h"
namespace llvm {
class IntrinsicLowering;
class SparcV8TargetMachine : public TargetMachine {
SparcV8InstrInfo InstrInfo;
TargetFrameInfo FrameInfo;
SparcV8JITInfo JITInfo;
public:
SparcV8TargetMachine(const Module &M, IntrinsicLowering *IL);
virtual const SparcV8InstrInfo &getInstrInfo() const { return InstrInfo; }
virtual const TargetFrameInfo &getFrameInfo() const { return FrameInfo; }
virtual const MRegisterInfo *getRegisterInfo() const {
return &InstrInfo.getRegisterInfo();
}
virtual TargetJITInfo *getJITInfo() {
return &JITInfo;
}
virtual const TargetSchedInfo &getSchedInfo() const { abort(); }
virtual const TargetRegInfo &getRegInfo() const { abort(); }
/// addPassesToEmitMachineCode - Add passes to the specified pass manager to
/// get machine code emitted. This uses a MachineCodeEmitter object to handle
/// actually outputting the machine code and resolving things like the address
/// of functions. This method should returns true if machine code emission is
/// not supported.
///
virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM,
MachineCodeEmitter &MCE);
virtual bool addPassesToEmitAssembly(PassManager &PM, std::ostream &Out);
};
} // end namespace llvm
#endif

View File

@@ -1156,12 +1156,18 @@ CreateCodeForFixedSizeAlloca(const TargetMachine& target,
unsigned numElements,
std::vector<MachineInstr*>& getMvec)
{
assert(tsize > 0 && "Illegal (zero) type size for alloca");
assert(result && result->getParent() &&
"Result value is not part of a function?");
Function *F = result->getParent()->getParent();
MachineFunction &mcInfo = MachineFunction::get(F);
// If the alloca is of zero bytes (which is perfectly legal) we bump it up to
// one byte. This is unnecessary, but I really don't want to break any
// fragile logic in this code. FIXME.
if (tsize == 0)
tsize = 1;
// Put the variable in the dynamically sized area of the frame if either:
// (a) The offset is too large to use as an immediate in load/stores
// (check LDX because all load/stores have the same-size immed. field).

View File

@@ -1422,6 +1422,8 @@ static bool isSafeToFoldLoadIntoInstruction(LoadInst &LI, Instruction &User) {
// really use alias analysis here, but for now we just do something simple.
for (++It; It != BasicBlock::iterator(&User); ++It) {
switch (It->getOpcode()) {
case Instruction::Malloc:
case Instruction::Free:
case Instruction::Store:
case Instruction::Call:
case Instruction::Invoke:

View File

@@ -18,12 +18,16 @@
#include "llvm/iTerminators.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "Support/Statistic.h"
using namespace llvm;
namespace {
Statistic<> NumExtracted("loop-extract", "Number of loops extracted");
// FIXME: This is not a function pass, but the PassManager doesn't allow
// Module passes to require FunctionPasses, so we can't get loop info if we're
// not a function pass.
@@ -35,8 +39,10 @@ namespace {
virtual bool runOnFunction(Function &F);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<LoopInfo>();
AU.addRequiredID(BreakCriticalEdgesID);
AU.addRequiredID(LoopSimplifyID);
AU.addRequired<DominatorSet>();
AU.addRequired<LoopInfo>();
}
};
@@ -59,6 +65,8 @@ bool LoopExtractor::runOnFunction(Function &F) {
if (LI.begin() == LI.end())
return false;
DominatorSet &DS = getAnalysis<DominatorSet>();
// If there is more than one top-level loop in this function, extract all of
// the loops.
bool Changed = false;
@@ -66,7 +74,8 @@ bool LoopExtractor::runOnFunction(Function &F) {
for (LoopInfo::iterator i = LI.begin(), e = LI.end(); i != e; ++i) {
if (NumLoops == 0) return Changed;
--NumLoops;
Changed |= (ExtractLoop(*i) != 0);
Changed |= ExtractLoop(DS, *i) != 0;
++NumExtracted;
}
} else {
// Otherwise there is exactly one top-level loop. If this function is more
@@ -93,7 +102,8 @@ bool LoopExtractor::runOnFunction(Function &F) {
if (ShouldExtractLoop) {
if (NumLoops == 0) return Changed;
--NumLoops;
Changed |= (ExtractLoop(TLL) != 0);
Changed |= ExtractLoop(DS, TLL) != 0;
++NumExtracted;
} else {
// Okay, this function is a minimal container around the specified loop.
// If we extract the loop, we will continue to just keep extracting it
@@ -102,7 +112,8 @@ bool LoopExtractor::runOnFunction(Function &F) {
for (Loop::iterator i = TLL->begin(), e = TLL->end(); i != e; ++i) {
if (NumLoops == 0) return Changed;
--NumLoops;
Changed |= (ExtractLoop(*i) != 0);
Changed |= ExtractLoop(DS, *i) != 0;
++NumExtracted;
}
}
}

View File

@@ -13,16 +13,16 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/BasicBlock.h"
#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "Support/Debug.h"
#include "Support/StringExtras.h"
#include <algorithm>
@@ -30,22 +30,13 @@
using namespace llvm;
namespace {
/// getFunctionArg - Return a pointer to F's ARGNOth argument.
///
Argument *getFunctionArg(Function *F, unsigned argno) {
Function::aiterator I = F->abegin();
std::advance(I, argno);
return I;
}
struct CodeExtractor {
class CodeExtractor {
typedef std::vector<Value*> Values;
typedef std::vector<std::pair<unsigned, unsigned> > PhiValChangesTy;
typedef std::map<PHINode*, PhiValChangesTy> PhiVal2ArgTy;
PhiVal2ArgTy PhiVal2Arg;
std::set<BasicBlock*> BlocksToExtract;
DominatorSet *DS;
public:
CodeExtractor(DominatorSet *ds = 0) : DS(ds) {}
Function *ExtractCodeRegion(const std::vector<BasicBlock*> &code);
private:
@@ -53,15 +44,9 @@ namespace {
BasicBlock *newHeader,
BasicBlock *newRootNode);
void processPhiNodeInputs(PHINode *Phi,
Values &inputs,
BasicBlock *newHeader,
BasicBlock *newRootNode);
void rewritePhiNodes(Function *F, BasicBlock *newFuncRoot);
Function *constructFunction(const Values &inputs,
const Values &outputs,
BasicBlock *header,
BasicBlock *newRootNode, BasicBlock *newHeader,
Function *oldFunction, Module *M);
@@ -75,95 +60,6 @@ namespace {
};
}
void CodeExtractor::processPhiNodeInputs(PHINode *Phi,
Values &inputs,
BasicBlock *codeReplacer,
BasicBlock *newFuncRoot) {
// Separate incoming values and BasicBlocks as internal/external. We ignore
// the case where both the value and BasicBlock are internal, because we don't
// need to do a thing.
std::vector<unsigned> EValEBB;
std::vector<unsigned> EValIBB;
std::vector<unsigned> IValEBB;
for (unsigned i = 0, e = Phi->getNumIncomingValues(); i != e; ++i) {
Value *phiVal = Phi->getIncomingValue(i);
if (Instruction *Inst = dyn_cast<Instruction>(phiVal)) {
if (BlocksToExtract.count(Inst->getParent())) {
if (!BlocksToExtract.count(Phi->getIncomingBlock(i)))
IValEBB.push_back(i);
} else {
if (BlocksToExtract.count(Phi->getIncomingBlock(i)))
EValIBB.push_back(i);
else
EValEBB.push_back(i);
}
} else if (Argument *Arg = dyn_cast<Argument>(phiVal)) {
// arguments are external
if (BlocksToExtract.count(Phi->getIncomingBlock(i)))
EValIBB.push_back(i);
else
EValEBB.push_back(i);
} else {
// Globals/Constants are internal, but considered `external' if they are
// coming from an external block.
if (!BlocksToExtract.count(Phi->getIncomingBlock(i)))
EValEBB.push_back(i);
}
}
// Both value and block are external. Need to group all of these, have an
// external phi, pass the result as an argument, and have THIS phi use that
// result.
if (EValEBB.size() > 0) {
if (EValEBB.size() == 1) {
// Now if it's coming from the newFuncRoot, it's that funky input
unsigned phiIdx = EValEBB[0];
if (!isa<Constant>(Phi->getIncomingValue(phiIdx))) {
PhiVal2Arg[Phi].push_back(std::make_pair(phiIdx, inputs.size()));
// We can just pass this value in as argument
inputs.push_back(Phi->getIncomingValue(phiIdx));
}
Phi->setIncomingBlock(phiIdx, newFuncRoot);
} else {
PHINode *externalPhi = new PHINode(Phi->getType(), "extPhi");
codeReplacer->getInstList().insert(codeReplacer->begin(), externalPhi);
for (std::vector<unsigned>::iterator i = EValEBB.begin(),
e = EValEBB.end(); i != e; ++i) {
externalPhi->addIncoming(Phi->getIncomingValue(*i),
Phi->getIncomingBlock(*i));
// We make these values invalid instead of deleting them because that
// would shift the indices of other values... The fixPhiNodes should
// clean these phi nodes up later.
Phi->setIncomingValue(*i, 0);
Phi->setIncomingBlock(*i, 0);
}
PhiVal2Arg[Phi].push_back(std::make_pair(Phi->getNumIncomingValues(),
inputs.size()));
// We can just pass this value in as argument
inputs.push_back(externalPhi);
}
}
// When the value is external, but block internal... just pass it in as
// argument, no change to phi node
for (std::vector<unsigned>::iterator i = EValIBB.begin(),
e = EValIBB.end(); i != e; ++i) {
// rewrite the phi input node to be an argument
PhiVal2Arg[Phi].push_back(std::make_pair(*i, inputs.size()));
inputs.push_back(Phi->getIncomingValue(*i));
}
// Value internal, block external this can happen if we are extracting a part
// of a loop.
for (std::vector<unsigned>::iterator i = IValEBB.begin(),
e = IValEBB.end(); i != e; ++i) {
assert(0 && "Cannot (YET) handle internal values via external blocks");
}
}
void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs,
BasicBlock *newHeader,
BasicBlock *newRootNode) {
@@ -173,8 +69,18 @@ void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs,
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
// If a used value is defined outside the region, it's an input. If an
// instruction is used outside the region, it's an output.
if (PHINode *Phi = dyn_cast<PHINode>(I)) {
processPhiNodeInputs(Phi, inputs, newHeader, newRootNode);
if (PHINode *PN = dyn_cast<PHINode>(I)) {
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
Value *V = PN->getIncomingValue(i);
if (!BlocksToExtract.count(PN->getIncomingBlock(i)) &&
(isa<Instruction>(V) || isa<Argument>(V)))
inputs.push_back(V);
else if (Instruction *opI = dyn_cast<Instruction>(V)) {
if (!BlocksToExtract.count(opI->getParent()))
inputs.push_back(opI);
} else if (isa<Argument>(V))
inputs.push_back(V);
}
} else {
// All other instructions go through the generic input finder
// Loop over the operands of each instruction (inputs)
@@ -192,59 +98,26 @@ void CodeExtractor::findInputsOutputs(Values &inputs, Values &outputs,
// Consider uses of this instruction (outputs)
for (Value::use_iterator UI = I->use_begin(), E = I->use_end();
UI != E; ++UI)
if (!BlocksToExtract.count(cast<Instruction>(*UI)->getParent()))
outputs.push_back(*UI);
if (!BlocksToExtract.count(cast<Instruction>(*UI)->getParent())) {
outputs.push_back(I);
break;
}
} // for: insts
} // for: basic blocks
}
void CodeExtractor::rewritePhiNodes(Function *F,
BasicBlock *newFuncRoot) {
// Write any changes that were saved before: use function arguments as inputs
for (PhiVal2ArgTy::iterator i = PhiVal2Arg.begin(), e = PhiVal2Arg.end();
i != e; ++i) {
PHINode *phi = i->first;
PhiValChangesTy &values = i->second;
for (unsigned cIdx = 0, ce = values.size(); cIdx != ce; ++cIdx)
{
unsigned phiValueIdx = values[cIdx].first, argNum = values[cIdx].second;
if (phiValueIdx < phi->getNumIncomingValues())
phi->setIncomingValue(phiValueIdx, getFunctionArg(F, argNum));
else
phi->addIncoming(getFunctionArg(F, argNum), newFuncRoot);
}
}
// Delete any invalid Phi node inputs that were marked as NULL previously
for (PhiVal2ArgTy::iterator i = PhiVal2Arg.begin(), e = PhiVal2Arg.end();
i != e; ++i) {
PHINode *phi = i->first;
for (unsigned idx = 0, end = phi->getNumIncomingValues(); idx != end; ++idx)
{
if (phi->getIncomingValue(idx) == 0 && phi->getIncomingBlock(idx) == 0) {
phi->removeIncomingValue(idx);
--idx;
--end;
}
}
}
// We are done with the saved values
PhiVal2Arg.clear();
}
/// constructFunction - make a function based on inputs and outputs, as follows:
/// f(in0, ..., inN, out0, ..., outN)
///
Function *CodeExtractor::constructFunction(const Values &inputs,
const Values &outputs,
BasicBlock *header,
BasicBlock *newRootNode,
BasicBlock *newHeader,
Function *oldFunction, Module *M) {
Function *oldFunction,
Module *M) {
DEBUG(std::cerr << "inputs: " << inputs.size() << "\n");
DEBUG(std::cerr << "outputs: " << outputs.size() << "\n");
BasicBlock *header = *BlocksToExtract.begin();
// This function returns unsigned, outputs will go back by reference.
Type *retTy = Type::UShortTy;
@@ -258,18 +131,11 @@ Function *CodeExtractor::constructFunction(const Values &inputs,
paramTy.push_back(value->getType());
}
// Add the types of the output values to the function's argument list, but
// make them pointer types for scalars
for (Values::const_iterator i = outputs.begin(),
e = outputs.end(); i != e; ++i) {
const Value *value = *i;
DEBUG(std::cerr << "instr used in func: " << value << "\n");
const Type *valueType = value->getType();
// Convert scalar types into a pointer of that type
if (valueType->isPrimitiveType()) {
valueType = PointerType::get(valueType);
}
paramTy.push_back(valueType);
// Add the types of the output values to the function's argument list.
for (Values::const_iterator I = outputs.begin(), E = outputs.end();
I != E; ++I) {
DEBUG(std::cerr << "instr used in func: " << *I << "\n");
paramTy.push_back(PointerType::get((*I)->getType()));
}
DEBUG(std::cerr << "Function type: " << retTy << " f(");
@@ -286,30 +152,37 @@ Function *CodeExtractor::constructFunction(const Values &inputs,
oldFunction->getName() + "_code", M);
newFunction->getBasicBlockList().push_back(newRootNode);
for (unsigned i = 0, e = inputs.size(); i != e; ++i) {
// Create an iterator to name all of the arguments we inserted.
Function::aiterator AI = newFunction->abegin();
// Rewrite all users of the inputs in the extracted region to use the
// arguments instead.
for (unsigned i = 0, e = inputs.size(); i != e; ++i, ++AI) {
AI->setName(inputs[i]->getName());
std::vector<User*> Users(inputs[i]->use_begin(), inputs[i]->use_end());
for (std::vector<User*>::iterator use = Users.begin(), useE = Users.end();
use != useE; ++use)
if (Instruction* inst = dyn_cast<Instruction>(*use))
if (BlocksToExtract.count(inst->getParent()))
inst->replaceUsesOfWith(inputs[i], getFunctionArg(newFunction, i));
inst->replaceUsesOfWith(inputs[i], AI);
}
// Set names for all of the output arguments.
for (unsigned i = 0, e = outputs.size(); i != e; ++i, ++AI)
AI->setName(outputs[i]->getName()+".out");
// Rewrite branches to basic blocks outside of the loop to new dummy blocks
// within the new function. This must be done before we lose track of which
// blocks were originally in the code region.
std::vector<User*> Users(header->use_begin(), header->use_end());
for (std::vector<User*>::iterator i = Users.begin(), e = Users.end();
i != e; ++i) {
if (BranchInst *inst = dyn_cast<BranchInst>(*i)) {
BasicBlock *BB = inst->getParent();
if (!BlocksToExtract.count(BB) && BB->getParent() == oldFunction) {
// The BasicBlock which contains the branch is not in the region
// modify the branch target to a new block
inst->replaceUsesOfWith(header, newHeader);
}
}
}
for (unsigned i = 0, e = Users.size(); i != e; ++i)
// The BasicBlock which contains the branch is not in the region
// modify the branch target to a new block
if (TerminatorInst *TI = dyn_cast<TerminatorInst>(Users[i]))
if (!BlocksToExtract.count(TI->getParent()) &&
TI->getParent()->getParent() == oldFunction)
TI->replaceUsesOfWith(header, newHeader);
return newFunction;
}
@@ -333,34 +206,30 @@ void
CodeExtractor::emitCallAndSwitchStatement(Function *newFunction,
BasicBlock *codeReplacer,
Values &inputs,
Values &outputs)
{
Values &outputs) {
// Emit a call to the new function, passing allocated memory for outputs and
// just plain inputs for non-scalars
std::vector<Value*> params(inputs);
for (Values::const_iterator i = outputs.begin(), e = outputs.end(); i != e;
++i) {
Value *Output = *i;
// Create allocas for scalar outputs
if (Output->getType()->isPrimitiveType()) {
AllocaInst *alloca =
new AllocaInst((*i)->getType(), 0, Output->getName()+".loc",
codeReplacer->getParent()->begin()->begin());
params.push_back(alloca);
// Get an iterator to the first output argument.
Function::aiterator OutputArgBegin = newFunction->abegin();
std::advance(OutputArgBegin, inputs.size());
LoadInst *load = new LoadInst(alloca, Output->getName()+".reload");
codeReplacer->getInstList().push_back(load);
std::vector<User*> Users((*i)->use_begin(), (*i)->use_end());
for (std::vector<User*>::iterator use = Users.begin(), useE =Users.end();
use != useE; ++use) {
if (Instruction* inst = dyn_cast<Instruction>(*use)) {
if (!BlocksToExtract.count(inst->getParent()))
inst->replaceUsesOfWith(*i, load);
}
}
} else {
params.push_back(*i);
for (unsigned i = 0, e = outputs.size(); i != e; ++i) {
Value *Output = outputs[i];
// Create allocas for scalar outputs
AllocaInst *alloca =
new AllocaInst(outputs[i]->getType(), 0, Output->getName()+".loc",
codeReplacer->getParent()->begin()->begin());
params.push_back(alloca);
LoadInst *load = new LoadInst(alloca, Output->getName()+".reload");
codeReplacer->getInstList().push_back(load);
std::vector<User*> Users(outputs[i]->use_begin(), outputs[i]->use_end());
for (unsigned u = 0, e = Users.size(); u != e; ++u) {
Instruction *inst = cast<Instruction>(Users[u]);
if (!BlocksToExtract.count(inst->getParent()))
inst->replaceUsesOfWith(outputs[i], load);
}
}
@@ -400,8 +269,12 @@ CodeExtractor::emitCallAndSwitchStatement(Function *newFunction,
// Restore values just before we exit
// FIXME: Use a GetElementPtr to bunch the outputs in a struct
for (unsigned out = 0, e = outputs.size(); out != e; ++out)
new StoreInst(outputs[out], getFunctionArg(newFunction, out),NTRet);
Function::aiterator OAI = OutputArgBegin;
for (unsigned out = 0, e = outputs.size(); out != e; ++out, ++OAI)
if (!DS ||
DS->dominates(cast<Instruction>(outputs[out])->getParent(),
TI->getParent()))
new StoreInst(outputs[out], OAI, NTRet);
}
// rewrite the original branch instruction with this new target
@@ -486,16 +359,36 @@ Function *CodeExtractor::ExtractCodeRegion(const std::vector<BasicBlock*> &code)
// Step 2: Construct new function based on inputs/outputs,
// Add allocas for all defs
Function *newFunction = constructFunction(inputs, outputs, newFuncRoot,
Function *newFunction = constructFunction(inputs, outputs, code[0],
newFuncRoot,
codeReplacer, oldFunction,
oldFunction->getParent());
rewritePhiNodes(newFunction, newFuncRoot);
emitCallAndSwitchStatement(newFunction, codeReplacer, inputs, outputs);
moveCodeToFunction(newFunction);
// Loop over all of the PHI nodes in the entry block (code[0]), and change any
// references to the old incoming edge to be the new incoming edge.
for (BasicBlock::iterator I = code[0]->begin();
PHINode *PN = dyn_cast<PHINode>(I); ++I)
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
if (!BlocksToExtract.count(PN->getIncomingBlock(i)))
PN->setIncomingBlock(i, newFuncRoot);
// Look at all successors of the codeReplacer block. If any of these blocks
// had PHI nodes in them, we need to update the "from" block to be the code
// replacer, not the original block in the extracted region.
std::vector<BasicBlock*> Succs(succ_begin(codeReplacer),
succ_end(codeReplacer));
for (unsigned i = 0, e = Succs.size(); i != e; ++i)
for (BasicBlock::iterator I = Succs[i]->begin();
PHINode *PN = dyn_cast<PHINode>(I); ++I)
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i)
if (BlocksToExtract.count(PN->getIncomingBlock(i)))
PN->setIncomingBlock(i, codeReplacer);
DEBUG(if (verifyFunction(*newFunction)) abort());
return newFunction;
}
@@ -503,14 +396,15 @@ Function *CodeExtractor::ExtractCodeRegion(const std::vector<BasicBlock*> &code)
/// ExtractCodeRegion - slurp a sequence of basic blocks into a brand new
/// function
///
Function* llvm::ExtractCodeRegion(const std::vector<BasicBlock*> &code) {
return CodeExtractor().ExtractCodeRegion(code);
Function* llvm::ExtractCodeRegion(DominatorSet &DS,
const std::vector<BasicBlock*> &code) {
return CodeExtractor(&DS).ExtractCodeRegion(code);
}
/// ExtractBasicBlock - slurp a natural loop into a brand new function
///
Function* llvm::ExtractLoop(Loop *L) {
return CodeExtractor().ExtractCodeRegion(L->getBlocks());
Function* llvm::ExtractLoop(DominatorSet &DS, Loop *L) {
return CodeExtractor(&DS).ExtractCodeRegion(L->getBlocks());
}
/// ExtractBasicBlock - slurp a basic block into a brand new function

View File

@@ -11,6 +11,7 @@ BYTECODE_LIBRARY=1
BUILD_ARCHIVE=1
DONT_BUILD_RELINKED=1
LIBRARYNAME=z
CPPFLAGS += -DNO_DUMMY_DECL=1
Source = adler32.c compress.c crc32.c gzio.c uncompr.c deflate.c trees.c \
zutil.c inflate.c infback.c inftrees.c inffast.c

View File

@@ -34,6 +34,10 @@ ifeq ($(OS),SunOS)
QMEXPECT:=$(LLVM_SRC_ROOT)/test/QMTest/expectations.sunos.qmr
endif
ifeq ($(OS),Darwin)
QMEXPECT:=$(LLVM_SRC_ROOT)/test/QMTest/expectations.darwin.qmr
endif
#
# This is configuration information used by the test suite. In QM Test, it's
# called a 'context.'

View File

@@ -11,7 +11,6 @@ TOOLNAME = llc
USEDLIBS = cwriter \
sparcv9 \
x86 \
powerpc \
selectiondag \
sparcv9regalloc \
sched \

View File

@@ -39,13 +39,12 @@ OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));
enum ArchName { noarch, X86, SparcV9, PowerPC, CBackend };
enum ArchName { noarch, X86, SparcV9, CBackend };
static cl::opt<ArchName>
Arch("march", cl::desc("Architecture to generate assembly for:"), cl::Prefix,
cl::values(clEnumValN(X86, "x86", " IA-32 (Pentium and above)"),
clEnumValN(SparcV9, "sparcv9", " SPARC V9"),
clEnumValN(PowerPC, "powerpc", " PowerPC (experimental)"),
clEnumValN(CBackend, "c", " C backend"),
0),
cl::init(noarch));
@@ -95,9 +94,6 @@ int main(int argc, char **argv) {
case SparcV9:
TargetMachineAllocator = allocateSparcV9TargetMachine;
break;
case PowerPC:
TargetMachineAllocator = allocatePowerPCTargetMachine;
break;
default:
// Decide what the default target machine should be, by looking at
// the module. This heuristic (ILP32, LE -> IA32; LP64, BE ->
@@ -106,9 +102,6 @@ int main(int argc, char **argv) {
if (mod.getEndianness() == Module::LittleEndian &&
mod.getPointerSize() == Module::Pointer32) {
TargetMachineAllocator = allocateX86TargetMachine;
} else if (mod.getEndianness() == Module::BigEndian &&
mod.getPointerSize() == Module::Pointer32) {
TargetMachineAllocator = allocatePowerPCTargetMachine;
} else if (mod.getEndianness() == Module::BigEndian &&
mod.getPointerSize() == Module::Pointer64) {
TargetMachineAllocator = allocateSparcV9TargetMachine;
@@ -119,8 +112,6 @@ int main(int argc, char **argv) {
TargetMachineAllocator = allocateX86TargetMachine;
#elif defined(sparc) || defined(__sparc__) || defined(__sparcv9)
TargetMachineAllocator = allocateSparcV9TargetMachine;
#elif defined(__POWERPC__) || defined(__ppc__) || defined(__APPLE__)
TargetMachineAllocator = allocatePowerPCTargetMachine;
#else
std::cerr << argv[0] << ": module does not specify a target to use. "
<< "You must use the -march option. If no native target is "