Compare commits
17 Commits
arcpatch-D
...
llvmorg-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
303b238cc3 | ||
|
|
c1d8934838 | ||
|
|
3c96135937 | ||
|
|
3c0d59f546 | ||
|
|
510529f5e1 | ||
|
|
df834c2b61 | ||
|
|
d0118041ec | ||
|
|
87340561e3 | ||
|
|
d118722f63 | ||
|
|
052debc4d8 | ||
|
|
9f115d2063 | ||
|
|
e2fb1d0251 | ||
|
|
3c5f2201c9 | ||
|
|
3f024e982f | ||
|
|
51a4de5f2e | ||
|
|
6babfa929c | ||
|
|
bb8b55b1e4 |
@@ -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 <filename>
|
||||
<br>
|
||||
Specify the name of the file loaded by the -profile-loader option.
|
||||
|
||||
@@ -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 <filename></tt><br>
|
||||
Preserve the symbols listed in the file <tt>filename</tt>.<p>
|
||||
|
||||
<li><tt>-internalize-public-api-list <list></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 <filename></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
|
||||
|
||||
@@ -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 <filename>
|
||||
<br>
|
||||
Specify the name of the file loaded by the -profile-loader option.
|
||||
|
||||
@@ -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/<<i>platform</i>>/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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
@@ -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
|
||||
& 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>
|
||||
|
||||
@@ -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<></tt> and <tt>AnalysisUsage::addRequiredTransitive<></tt> methods</a></li>
|
||||
<li><a href="#AU::addPreserved">The <tt>AnalysisUsage::addPreserved<></tt> method</a></li>
|
||||
<li><a href="#AU::examples">Example implementations of <tt>getAnalysisUsage</tt></a></li>
|
||||
<li><a href="#getAnalysis">The <tt>getAnalysis<></tt> and <tt>getAnalysisToUpdate<></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 &)</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
|
||||
&)</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
|
||||
&)</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 &)</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
|
||||
&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><<b>class</b> PassClass>
|
||||
AnalysisUsage &AnalysisUsage::addRequired();
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="AU::addRequired">The <tt>AnalysisUsage::addRequired<></tt> and <tt>AnalysisUsage::addRequiredTransitive<></tt> methods</a>
|
||||
</div>
|
||||
|
||||
<i>// addPreserved - Add the specified pass to the set of analyses preserved by
|
||||
// this pass</i>
|
||||
<b>template</b><<b>class</b> PassClass>
|
||||
AnalysisUsage &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<></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<></tt> method</a>
|
||||
<a name="getAnalysis">The <tt>getAnalysis<></tt> and <tt>getAnalysisToUpdate<></tt> methods</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The <tt>Pass::getAnalysis<></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<></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><<b>typename</b> PassClass>
|
||||
AnalysisType &getAnalysis();
|
||||
bool LICM::runOnFunction(Function &F) {
|
||||
LoopInfo &LI = getAnalysis<LoopInfo>();
|
||||
...
|
||||
}
|
||||
</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<DominatorSet>()) {
|
||||
<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>
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -101,7 +101,7 @@ void AliasSet::addCallSite(CallSite CS, AliasAnalysis &AA) {
|
||||
return;
|
||||
else if (AA.onlyReadsMemory(F)) {
|
||||
AliasTy = MayAlias;
|
||||
AccessTy = Refs;
|
||||
AccessTy |= Refs;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../..
|
||||
DIRS = CBackend X86 SparcV9 PowerPC
|
||||
DIRS = CBackend X86 SparcV9
|
||||
LIBRARYNAME = target
|
||||
BUILD_ARCHIVE = 1
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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>;
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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]>;
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
@@ -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!");
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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$
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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])){
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
*/
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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]>;
|
||||
@@ -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());
|
||||
}
|
||||
@@ -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
|
||||
@@ -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).
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.'
|
||||
|
||||
@@ -11,7 +11,6 @@ TOOLNAME = llc
|
||||
USEDLIBS = cwriter \
|
||||
sparcv9 \
|
||||
x86 \
|
||||
powerpc \
|
||||
selectiondag \
|
||||
sparcv9regalloc \
|
||||
sched \
|
||||
|
||||
@@ -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 "
|
||||
|
||||
Reference in New Issue
Block a user