Update LLVM to 91430.
This commit is contained in:
parent
06f9d4012f
commit
571945e6af
@ -191,7 +191,13 @@ set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/lib )
|
||||
add_llvm_definitions( -D__STDC_LIMIT_MACROS )
|
||||
add_llvm_definitions( -D__STDC_CONSTANT_MACROS )
|
||||
|
||||
option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." ON)
|
||||
# MSVC has a gazillion warnings with this.
|
||||
if( MSVC )
|
||||
option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." OFF)
|
||||
else( MSVC )
|
||||
option(LLVM_ENABLE_WARNINGS "Enable compiler warnings." ON)
|
||||
endif()
|
||||
|
||||
option(LLVM_ENABLE_PEDANTIC "Compile with pedantic enabled." ON)
|
||||
option(LLVM_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF)
|
||||
|
||||
|
3
Makefile
3
Makefile
@ -66,8 +66,7 @@ ifeq ($(MAKECMDGOALS),tools-only)
|
||||
endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),install-clang)
|
||||
DIRS := tools/clang/tools/driver tools/clang/tools/clang-cc \
|
||||
tools/clang/lib/Headers tools/clang/docs
|
||||
DIRS := tools/clang/tools/driver tools/clang/lib/Headers tools/clang/docs
|
||||
OPTIONAL_DIRS :=
|
||||
NO_INSTALL = 1
|
||||
endif
|
||||
|
@ -313,7 +313,7 @@ endif
|
||||
# Location of the plugin header file for gold.
|
||||
BINUTILS_INCDIR := @BINUTILS_INCDIR@
|
||||
|
||||
C_INCLUDE_DIRS := @C_INCLUDE_DISR@
|
||||
C_INCLUDE_DIRS := @C_INCLUDE_DIRS@
|
||||
CXX_INCLUDE_ROOT := @CXX_INCLUDE_ROOT@
|
||||
CXX_INCLUDE_ARCH := @CXX_INCLUDE_ARCH@
|
||||
CXX_INCLUDE_32BIT_DIR = @CXX_INCLUDE_32BIT_DIR@
|
||||
|
@ -672,7 +672,7 @@ case "$withval" in
|
||||
*) AC_MSG_ERROR([Invalid path for --with-ocaml-libdir. Provide full path]) ;;
|
||||
esac
|
||||
|
||||
AC_ARG_WITH(c-include-dir,
|
||||
AC_ARG_WITH(c-include-dirs,
|
||||
AS_HELP_STRING([--with-c-include-dirs],
|
||||
[Colon separated list of directories clang will search for headers]),,
|
||||
withval="")
|
||||
|
@ -1,14 +1,25 @@
|
||||
# atomic builtins are required for threading support.
|
||||
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
|
||||
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#endif
|
||||
int main() {
|
||||
#ifdef _MSC_VER
|
||||
volatile LONG val = 1;
|
||||
MemoryBarrier();
|
||||
InterlockedCompareExchange(&val, 0, 1);
|
||||
InterlockedIncrement(&val);
|
||||
InterlockedDecrement(&val);
|
||||
#else
|
||||
volatile unsigned long val = 1;
|
||||
__sync_synchronize();
|
||||
__sync_val_compare_and_swap(&val, 1, 0);
|
||||
__sync_add_and_fetch(&val, 1);
|
||||
__sync_sub_and_fetch(&val, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
" LLVM_MULTITHREADED)
|
||||
|
6
configure
vendored
6
configure
vendored
@ -5286,9 +5286,9 @@ echo "$as_me: error: Invalid path for --with-ocaml-libdir. Provide full path" >&
|
||||
esac
|
||||
|
||||
|
||||
# Check whether --with-c-include-dir was given.
|
||||
if test "${with_c_include_dir+set}" = set; then
|
||||
withval=$with_c_include_dir;
|
||||
# Check whether --with-c-include-dirs was given.
|
||||
if test "${with_c_include_dirs+set}" = set; then
|
||||
withval=$with_c_include_dirs;
|
||||
else
|
||||
withval=""
|
||||
fi
|
||||
|
@ -17,28 +17,28 @@ The ReST source lives in the directory 'tools/llvmc/doc'. -->
|
||||
<div class="contents topic" id="contents">
|
||||
<p class="topic-title first">Contents</p>
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#introduction" id="id4">Introduction</a></li>
|
||||
<li><a class="reference internal" href="#compiling-with-llvmc" id="id5">Compiling with LLVMC</a></li>
|
||||
<li><a class="reference internal" href="#predefined-options" id="id6">Predefined options</a></li>
|
||||
<li><a class="reference internal" href="#compiling-llvmc-plugins" id="id7">Compiling LLVMC plugins</a></li>
|
||||
<li><a class="reference internal" href="#compiling-standalone-llvmc-based-drivers" id="id8">Compiling standalone LLVMC-based drivers</a></li>
|
||||
<li><a class="reference internal" href="#customizing-llvmc-the-compilation-graph" id="id9">Customizing LLVMC: the compilation graph</a></li>
|
||||
<li><a class="reference internal" href="#describing-options" id="id10">Describing options</a><ul>
|
||||
<li><a class="reference internal" href="#external-options" id="id11">External options</a></li>
|
||||
<li><a class="reference internal" href="#introduction" id="id8">Introduction</a></li>
|
||||
<li><a class="reference internal" href="#compiling-with-llvmc" id="id9">Compiling with LLVMC</a></li>
|
||||
<li><a class="reference internal" href="#predefined-options" id="id10">Predefined options</a></li>
|
||||
<li><a class="reference internal" href="#compiling-llvmc-plugins" id="id11">Compiling LLVMC plugins</a></li>
|
||||
<li><a class="reference internal" href="#compiling-standalone-llvmc-based-drivers" id="id12">Compiling standalone LLVMC-based drivers</a></li>
|
||||
<li><a class="reference internal" href="#customizing-llvmc-the-compilation-graph" id="id13">Customizing LLVMC: the compilation graph</a></li>
|
||||
<li><a class="reference internal" href="#describing-options" id="id14">Describing options</a><ul>
|
||||
<li><a class="reference internal" href="#external-options" id="id15">External options</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#conditional-evaluation" id="id12">Conditional evaluation</a></li>
|
||||
<li><a class="reference internal" href="#writing-a-tool-description" id="id13">Writing a tool description</a><ul>
|
||||
<li><a class="reference internal" href="#actions" id="id14">Actions</a></li>
|
||||
<li><a class="reference internal" href="#conditional-evaluation" id="id16">Conditional evaluation</a></li>
|
||||
<li><a class="reference internal" href="#writing-a-tool-description" id="id17">Writing a tool description</a><ul>
|
||||
<li><a class="reference internal" href="#id5" id="id18">Actions</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a class="reference internal" href="#language-map" id="id15">Language map</a></li>
|
||||
<li><a class="reference internal" href="#option-preprocessor" id="id16">Option preprocessor</a></li>
|
||||
<li><a class="reference internal" href="#more-advanced-topics" id="id17">More advanced topics</a><ul>
|
||||
<li><a class="reference internal" href="#hooks-and-environment-variables" id="id18">Hooks and environment variables</a></li>
|
||||
<li><a class="reference internal" href="#how-plugins-are-loaded" id="id19">How plugins are loaded</a></li>
|
||||
<li><a class="reference internal" href="#debugging" id="id20">Debugging</a></li>
|
||||
<li><a class="reference internal" href="#conditioning-on-the-executable-name" id="id21">Conditioning on the executable name</a></li>
|
||||
<li><a class="reference internal" href="#language-map" id="id19">Language map</a></li>
|
||||
<li><a class="reference internal" href="#option-preprocessor" id="id20">Option preprocessor</a></li>
|
||||
<li><a class="reference internal" href="#more-advanced-topics" id="id21">More advanced topics</a><ul>
|
||||
<li><a class="reference internal" href="#hooks-and-environment-variables" id="id22">Hooks and environment variables</a></li>
|
||||
<li><a class="reference internal" href="#how-plugins-are-loaded" id="id23">How plugins are loaded</a></li>
|
||||
<li><a class="reference internal" href="#debugging" id="id24">Debugging</a></li>
|
||||
<li><a class="reference internal" href="#conditioning-on-the-executable-name" id="id25">Conditioning on the executable name</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
@ -46,7 +46,7 @@ The ReST source lives in the directory 'tools/llvmc/doc'. -->
|
||||
<div class="doc_author">
|
||||
<p>Written by <a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a></p>
|
||||
</div><div class="section" id="introduction">
|
||||
<h1><a class="toc-backref" href="#id4">Introduction</a></h1>
|
||||
<h1><a class="toc-backref" href="#id8">Introduction</a></h1>
|
||||
<p>LLVMC is a generic compiler driver, designed to be customizable and
|
||||
extensible. It plays the same role for LLVM as the <tt class="docutils literal"><span class="pre">gcc</span></tt> program
|
||||
does for GCC - LLVMC's job is essentially to transform a set of input
|
||||
@ -63,7 +63,7 @@ example, as a build tool for game resources.</p>
|
||||
need to be familiar with it to customize LLVMC.</p>
|
||||
</div>
|
||||
<div class="section" id="compiling-with-llvmc">
|
||||
<h1><a class="toc-backref" href="#id5">Compiling with LLVMC</a></h1>
|
||||
<h1><a class="toc-backref" href="#id9">Compiling with LLVMC</a></h1>
|
||||
<p>LLVMC tries hard to be as compatible with <tt class="docutils literal"><span class="pre">gcc</span></tt> as possible,
|
||||
although there are some small differences. Most of the time, however,
|
||||
you shouldn't be able to notice them:</p>
|
||||
@ -100,7 +100,7 @@ hello
|
||||
possible to choose the <tt class="docutils literal"><span class="pre">clang</span></tt> compiler with the <tt class="docutils literal"><span class="pre">-clang</span></tt> option.</p>
|
||||
</div>
|
||||
<div class="section" id="predefined-options">
|
||||
<h1><a class="toc-backref" href="#id6">Predefined options</a></h1>
|
||||
<h1><a class="toc-backref" href="#id10">Predefined options</a></h1>
|
||||
<p>LLVMC has some built-in options that can't be overridden in the
|
||||
configuration libraries:</p>
|
||||
<ul class="simple">
|
||||
@ -137,7 +137,7 @@ their standard meaning.</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="compiling-llvmc-plugins">
|
||||
<h1><a class="toc-backref" href="#id7">Compiling LLVMC plugins</a></h1>
|
||||
<h1><a class="toc-backref" href="#id11">Compiling LLVMC plugins</a></h1>
|
||||
<p>It's easiest to start working on your own LLVMC plugin by copying the
|
||||
skeleton project which lives under <tt class="docutils literal"><span class="pre">$LLVMC_DIR/plugins/Simple</span></tt>:</p>
|
||||
<pre class="literal-block">
|
||||
@ -176,7 +176,7 @@ $ llvmc -load $LLVM_DIR/Release/lib/plugin_llvmc_Simple.so
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="compiling-standalone-llvmc-based-drivers">
|
||||
<h1><a class="toc-backref" href="#id8">Compiling standalone LLVMC-based drivers</a></h1>
|
||||
<h1><a class="toc-backref" href="#id12">Compiling standalone LLVMC-based drivers</a></h1>
|
||||
<p>By default, the <tt class="docutils literal"><span class="pre">llvmc</span></tt> executable consists of a driver core plus several
|
||||
statically linked plugins (<tt class="docutils literal"><span class="pre">Base</span></tt> and <tt class="docutils literal"><span class="pre">Clang</span></tt> at the moment). You can
|
||||
produce a standalone LLVMC-based driver executable by linking the core with your
|
||||
@ -215,7 +215,7 @@ $ make LLVMC_BUILTIN_PLUGINS=""
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="customizing-llvmc-the-compilation-graph">
|
||||
<h1><a class="toc-backref" href="#id9">Customizing LLVMC: the compilation graph</a></h1>
|
||||
<h1><a class="toc-backref" href="#id13">Customizing LLVMC: the compilation graph</a></h1>
|
||||
<p>Each TableGen configuration file should include the common
|
||||
definitions:</p>
|
||||
<pre class="literal-block">
|
||||
@ -283,7 +283,7 @@ debugging), run <tt class="docutils literal"><span class="pre">llvmc</span> <spa
|
||||
<tt class="docutils literal"><span class="pre">gsview</span></tt> installed for this to work properly.</p>
|
||||
</div>
|
||||
<div class="section" id="describing-options">
|
||||
<h1><a class="toc-backref" href="#id10">Describing options</a></h1>
|
||||
<h1><a class="toc-backref" href="#id14">Describing options</a></h1>
|
||||
<p>Command-line options that the plugin supports are defined by using an
|
||||
<tt class="docutils literal"><span class="pre">OptionList</span></tt>:</p>
|
||||
<pre class="literal-block">
|
||||
@ -342,6 +342,11 @@ the <tt class="docutils literal"><span class="pre">--help</span></tt> output (bu
|
||||
output).</li>
|
||||
<li><tt class="docutils literal"><span class="pre">really_hidden</span></tt> - the option will not be mentioned in any help
|
||||
output.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">comma_separated</span></tt> - Indicates that any commas specified for an option's
|
||||
value should be used to split the value up into multiple values for the
|
||||
option. This property is valid only for list options. In conjunction with
|
||||
<tt class="docutils literal"><span class="pre">forward_value</span></tt> can be used to implement option forwarding in style of
|
||||
gcc's <tt class="docutils literal"><span class="pre">-Wa,</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">multi_val</span> <span class="pre">n</span></tt> - this option takes <em>n</em> arguments (can be useful in some
|
||||
special cases). Usage example: <tt class="docutils literal"><span class="pre">(parameter_list_option</span> <span class="pre">"foo",</span> <span class="pre">(multi_val</span>
|
||||
<span class="pre">3))</span></tt>; the command-line syntax is '-foo a b c'. Only list options can have
|
||||
@ -352,13 +357,13 @@ parameter), or a boolean (if it is a switch; boolean constants are called
|
||||
<tt class="docutils literal"><span class="pre">true</span></tt> and <tt class="docutils literal"><span class="pre">false</span></tt>). List options can't have this attribute. Usage
|
||||
examples: <tt class="docutils literal"><span class="pre">(switch_option</span> <span class="pre">"foo",</span> <span class="pre">(init</span> <span class="pre">true))</span></tt>; <tt class="docutils literal"><span class="pre">(prefix_option</span> <span class="pre">"bar",</span>
|
||||
<span class="pre">(init</span> <span class="pre">"baz"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">extern</span></tt> - this option is defined in some other plugin, see below.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">extern</span></tt> - this option is defined in some other plugin, see <a class="reference internal" href="#extern">below</a>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="section" id="external-options">
|
||||
<h2><a class="toc-backref" href="#id11">External options</a></h2>
|
||||
<span id="extern"></span><h2><a class="toc-backref" href="#id15">External options</a></h2>
|
||||
<p>Sometimes, when linking several plugins together, one plugin needs to
|
||||
access options defined in some other plugin. Because of the way
|
||||
options are implemented, such options must be marked as
|
||||
@ -374,7 +379,7 @@ ignored. See also the section on plugin <a class="reference internal" href="#pri
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="conditional-evaluation">
|
||||
<span id="case"></span><h1><a class="toc-backref" href="#id12">Conditional evaluation</a></h1>
|
||||
<span id="case"></span><h1><a class="toc-backref" href="#id16">Conditional evaluation</a></h1>
|
||||
<p>The 'case' construct is the main means by which programmability is
|
||||
achieved in LLVMC. It can be used to calculate edge weights, program
|
||||
actions and modify the shell commands to be executed. The 'case'
|
||||
@ -433,7 +438,7 @@ a given value.
|
||||
Example: <tt class="docutils literal"><span class="pre">(parameter_equals</span> <span class="pre">"W",</span> <span class="pre">"all")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">element_in_list</span></tt> - Returns true if a command-line parameter
|
||||
list contains a given value.
|
||||
Example: <tt class="docutils literal"><span class="pre">(parameter_in_list</span> <span class="pre">"l",</span> <span class="pre">"pthread")</span></tt>.</li>
|
||||
Example: <tt class="docutils literal"><span class="pre">(element_in_list</span> <span class="pre">"l",</span> <span class="pre">"pthread")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">input_languages_contain</span></tt> - Returns true if a given language
|
||||
belongs to the current input language set.
|
||||
Example: <tt class="docutils literal"><span class="pre">(input_languages_contain</span> <span class="pre">"c++")</span></tt>.</li>
|
||||
@ -475,7 +480,7 @@ argument. Example: <tt class="docutils literal"><span class="pre">(not</span> <s
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="writing-a-tool-description">
|
||||
<h1><a class="toc-backref" href="#id13">Writing a tool description</a></h1>
|
||||
<h1><a class="toc-backref" href="#id17">Writing a tool description</a></h1>
|
||||
<p>As was said earlier, nodes in the compilation graph represent tools,
|
||||
which are described separately. A tool definition looks like this
|
||||
(taken from the <tt class="docutils literal"><span class="pre">include/llvm/CompilerDriver/Tools.td</span></tt> file):</p>
|
||||
@ -512,12 +517,12 @@ list of input files and joins them together. Used for linkers.</li>
|
||||
tools are passed to this tool.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">actions</span></tt> - A single big <tt class="docutils literal"><span class="pre">case</span></tt> expression that specifies how
|
||||
this tool reacts on command-line options (described in more detail
|
||||
below).</li>
|
||||
<a class="reference internal" href="#actions">below</a>).</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="section" id="actions">
|
||||
<h2><a class="toc-backref" href="#id14">Actions</a></h2>
|
||||
<div class="section" id="id5">
|
||||
<span id="actions"></span><h2><a class="toc-backref" href="#id18">Actions</a></h2>
|
||||
<p>A tool often needs to react to command-line options, and this is
|
||||
precisely what the <tt class="docutils literal"><span class="pre">actions</span></tt> property is for. The next example
|
||||
illustrates this feature:</p>
|
||||
@ -550,28 +555,31 @@ like a linker.</p>
|
||||
<li><p class="first">Possible actions:</p>
|
||||
<blockquote>
|
||||
<ul class="simple">
|
||||
<li><tt class="docutils literal"><span class="pre">append_cmd</span></tt> - append a string to the tool invocation
|
||||
command.
|
||||
Example: <tt class="docutils literal"><span class="pre">(case</span> <span class="pre">(switch_on</span> <span class="pre">"pthread"),</span> <span class="pre">(append_cmd</span>
|
||||
<span class="pre">"-lpthread"))</span></tt></li>
|
||||
<li><tt class="docutils literal"><span class="pre">error</span></tt> - exit with error.
|
||||
<li><tt class="docutils literal"><span class="pre">append_cmd</span></tt> - Append a string to the tool invocation command.
|
||||
Example: <tt class="docutils literal"><span class="pre">(case</span> <span class="pre">(switch_on</span> <span class="pre">"pthread"),</span> <span class="pre">(append_cmd</span> <span class="pre">"-lpthread"))</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">error</span></tt> - Exit with error.
|
||||
Example: <tt class="docutils literal"><span class="pre">(error</span> <span class="pre">"Mixing</span> <span class="pre">-c</span> <span class="pre">and</span> <span class="pre">-S</span> <span class="pre">is</span> <span class="pre">not</span> <span class="pre">allowed!")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">warning</span></tt> - print a warning.
|
||||
<li><tt class="docutils literal"><span class="pre">warning</span></tt> - Print a warning.
|
||||
Example: <tt class="docutils literal"><span class="pre">(warning</span> <span class="pre">"Specifying</span> <span class="pre">both</span> <span class="pre">-O1</span> <span class="pre">and</span> <span class="pre">-O2</span> <span class="pre">is</span> <span class="pre">meaningless!")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">forward</span></tt> - forward an option unchanged. Example: <tt class="docutils literal"><span class="pre">(forward</span> <span class="pre">"Wall")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">forward_as</span></tt> - Change the name of an option, but forward the
|
||||
argument unchanged.
|
||||
<li><tt class="docutils literal"><span class="pre">forward</span></tt> - Forward the option unchanged.
|
||||
Example: <tt class="docutils literal"><span class="pre">(forward</span> <span class="pre">"Wall")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">forward_as</span></tt> - Change the option's name, but forward the argument
|
||||
unchanged.
|
||||
Example: <tt class="docutils literal"><span class="pre">(forward_as</span> <span class="pre">"O0",</span> <span class="pre">"--disable-optimization")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">output_suffix</span></tt> - modify the output suffix of this
|
||||
tool.
|
||||
<li><tt class="docutils literal"><span class="pre">forward_value</span></tt> - Forward only option's value. Cannot be used with switch
|
||||
options (since they don't have values), but works fine with lists.
|
||||
Example: <tt class="docutils literal"><span class="pre">(forward_value</span> <span class="pre">"Wa,")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">forward_transformed_value</span></tt> - As above, but applies a hook to the
|
||||
option's value before forwarding (see <a class="reference internal" href="#hooks">below</a>). When
|
||||
<tt class="docutils literal"><span class="pre">forward_transformed_value</span></tt> is applied to a list
|
||||
option, the hook must have signature
|
||||
<tt class="docutils literal"><span class="pre">std::string</span> <span class="pre">hooks::HookName</span> <span class="pre">(const</span> <span class="pre">std::vector<std::string>&)</span></tt>.
|
||||
Example: <tt class="docutils literal"><span class="pre">(forward_transformed_value</span> <span class="pre">"m",</span> <span class="pre">"ConvertToMAttr")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">output_suffix</span></tt> - Modify the output suffix of this tool.
|
||||
Example: <tt class="docutils literal"><span class="pre">(output_suffix</span> <span class="pre">"i")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">stop_compilation</span></tt> - stop compilation after this tool processes
|
||||
its input. Used without arguments.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">unpack_values</span></tt> - used for for splitting and forwarding
|
||||
comma-separated lists of options, e.g. <tt class="docutils literal"><span class="pre">-Wa,-foo=bar,-baz</span></tt> is
|
||||
converted to <tt class="docutils literal"><span class="pre">-foo=bar</span> <span class="pre">-baz</span></tt> and appended to the tool invocation
|
||||
command.
|
||||
Example: <tt class="docutils literal"><span class="pre">(unpack_values</span> <span class="pre">"Wa,")</span></tt>.</li>
|
||||
<li><tt class="docutils literal"><span class="pre">stop_compilation</span></tt> - Stop compilation after this tool processes its
|
||||
input. Used without arguments.
|
||||
Example: <tt class="docutils literal"><span class="pre">(stop_compilation)</span></tt>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
</li>
|
||||
@ -579,7 +587,7 @@ Example: <tt class="docutils literal"><span class="pre">(unpack_values</span> <s
|
||||
</div>
|
||||
</div>
|
||||
<div class="section" id="language-map">
|
||||
<h1><a class="toc-backref" href="#id15">Language map</a></h1>
|
||||
<h1><a class="toc-backref" href="#id19">Language map</a></h1>
|
||||
<p>If you are adding support for a new language to LLVMC, you'll need to
|
||||
modify the language map, which defines mappings from file extensions
|
||||
to language names. It is used to choose the proper toolchain(s) for a
|
||||
@ -602,7 +610,7 @@ multiple output languages, for nodes "inside" the graph the input and
|
||||
output languages should match. This is enforced at compile-time.</p>
|
||||
</div>
|
||||
<div class="section" id="option-preprocessor">
|
||||
<h1><a class="toc-backref" href="#id16">Option preprocessor</a></h1>
|
||||
<h1><a class="toc-backref" href="#id20">Option preprocessor</a></h1>
|
||||
<p>It is sometimes useful to run error-checking code before processing the
|
||||
compilation graph. For example, if optimization options "-O1" and "-O2" are
|
||||
implemented as switches, we might want to output a warning if the user invokes
|
||||
@ -629,9 +637,9 @@ in <tt class="docutils literal"><span class="pre">OptionPreprocessor</span></tt>
|
||||
convenience, <tt class="docutils literal"><span class="pre">unset_option</span></tt> also works on lists.</p>
|
||||
</div>
|
||||
<div class="section" id="more-advanced-topics">
|
||||
<h1><a class="toc-backref" href="#id17">More advanced topics</a></h1>
|
||||
<h1><a class="toc-backref" href="#id21">More advanced topics</a></h1>
|
||||
<div class="section" id="hooks-and-environment-variables">
|
||||
<span id="hooks"></span><h2><a class="toc-backref" href="#id18">Hooks and environment variables</a></h2>
|
||||
<span id="hooks"></span><h2><a class="toc-backref" href="#id22">Hooks and environment variables</a></h2>
|
||||
<p>Normally, LLVMC executes programs from the system <tt class="docutils literal"><span class="pre">PATH</span></tt>. Sometimes,
|
||||
this is not sufficient: for example, we may want to specify tool paths
|
||||
or names in the configuration file. This can be easily achieved via
|
||||
@ -664,7 +672,7 @@ the <tt class="docutils literal"><span class="pre">case</span></tt> expression (
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section" id="how-plugins-are-loaded">
|
||||
<span id="priorities"></span><h2><a class="toc-backref" href="#id19">How plugins are loaded</a></h2>
|
||||
<span id="priorities"></span><h2><a class="toc-backref" href="#id23">How plugins are loaded</a></h2>
|
||||
<p>It is possible for LLVMC plugins to depend on each other. For example,
|
||||
one can create edges between nodes defined in some other plugin. To
|
||||
make this work, however, that plugin should be loaded first. To
|
||||
@ -680,7 +688,7 @@ with 0. Therefore, the plugin with the highest priority value will be
|
||||
loaded last.</p>
|
||||
</div>
|
||||
<div class="section" id="debugging">
|
||||
<h2><a class="toc-backref" href="#id20">Debugging</a></h2>
|
||||
<h2><a class="toc-backref" href="#id24">Debugging</a></h2>
|
||||
<p>When writing LLVMC plugins, it can be useful to get a visual view of
|
||||
the resulting compilation graph. This can be achieved via the command
|
||||
line option <tt class="docutils literal"><span class="pre">--view-graph</span></tt>. This command assumes that <a class="reference external" href="http://www.graphviz.org/">Graphviz</a> and
|
||||
@ -696,7 +704,7 @@ perform any compilation tasks and returns the number of encountered
|
||||
errors as its status code.</p>
|
||||
</div>
|
||||
<div class="section" id="conditioning-on-the-executable-name">
|
||||
<h2><a class="toc-backref" href="#id21">Conditioning on the executable name</a></h2>
|
||||
<h2><a class="toc-backref" href="#id25">Conditioning on the executable name</a></h2>
|
||||
<p>For now, the executable name (the value passed to the driver in <tt class="docutils literal"><span class="pre">argv[0]</span></tt>) is
|
||||
accessible only in the C++ code (i.e. hooks). Use the following code:</p>
|
||||
<pre class="literal-block">
|
||||
@ -704,12 +712,16 @@ namespace llvmc {
|
||||
extern const char* ProgramName;
|
||||
}
|
||||
|
||||
namespace hooks {
|
||||
|
||||
std::string MyHook() {
|
||||
//...
|
||||
if (strcmp(ProgramName, "mydriver") == 0) {
|
||||
//...
|
||||
|
||||
}
|
||||
|
||||
} // end namespace hooks
|
||||
</pre>
|
||||
<p>In general, you're encouraged not to make the behaviour dependent on the
|
||||
executable file name, and use command-line switches instead. See for example how
|
||||
@ -727,7 +739,7 @@ the <tt class="docutils literal"><span class="pre">Base</span></tt> plugin behav
|
||||
<a href="mailto:foldr@codedgers.com">Mikhail Glushenkov</a><br />
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br />
|
||||
|
||||
Last modified: $Date: 2009-10-26 02:35:46 +0100 (Mon, 26 Oct 2009) $
|
||||
Last modified: $Date: 2009-12-07 19:26:24 +0100 (Mon, 07 Dec 2009) $
|
||||
</address></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -252,7 +252,8 @@ software you will need.</p>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cygwin/Win32</td>
|
||||
<td>x86<sup><a href="#pf_1">1</a>,<a href="#pf_8">8</a></sup></td>
|
||||
<td>x86<sup><a href="#pf_1">1</a>,<a href="#pf_8">8</a>,
|
||||
<a href="#pf_11">11</a></sup></td>
|
||||
<td>GCC 3.4.X, binutils 2.15</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -331,6 +332,9 @@ up</a></li>
|
||||
before any Windows-based versions such as Strawberry Perl and
|
||||
ActivePerl, as these have Windows-specifics that will cause the
|
||||
build to fail.</a></li>
|
||||
<li><a name="pf_11">In general, LLVM modules requiring dynamic linking can
|
||||
not be built on Windows. However, you can build LLVM tools using
|
||||
<i>"make tools-only"</i>.</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
@ -1636,7 +1640,7 @@ out:</p>
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.x10sys.com/rspencer/">Reid Spencer</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2009-11-04 07:15:28 +0100 (Wed, 04 Nov 2009) $
|
||||
Last modified: $Date: 2009-12-09 18:26:02 +0100 (Wed, 09 Dec 2009) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -5,7 +5,7 @@
|
||||
<title>LLVM Assembly Language Reference Manual</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="author" content="Chris Lattner">
|
||||
<meta name="description"
|
||||
<meta name="description"
|
||||
content="LLVM Assembly Language Reference Manual.">
|
||||
<link rel="stylesheet" href="llvm.css" type="text/css">
|
||||
</head>
|
||||
@ -54,7 +54,7 @@
|
||||
<li><a href="#typesystem">Type System</a>
|
||||
<ol>
|
||||
<li><a href="#t_classifications">Type Classifications</a></li>
|
||||
<li><a href="#t_primitive">Primitive Types</a>
|
||||
<li><a href="#t_primitive">Primitive Types</a>
|
||||
<ol>
|
||||
<li><a href="#t_integer">Integer Type</a></li>
|
||||
<li><a href="#t_floating">Floating Point Types</a></li>
|
||||
@ -576,7 +576,7 @@ define i32 @main() { <i>; i32()* </i>
|
||||
Symbols with "<tt>common</tt>" linkage are merged in the same way as
|
||||
<tt>weak symbols</tt>, and they may not be deleted if unreferenced.
|
||||
<tt>common</tt> symbols may not have an explicit section,
|
||||
must have a zero initializer, and may not be marked '<a
|
||||
must have a zero initializer, and may not be marked '<a
|
||||
href="#globalvars"><tt>constant</tt></a>'. Functions and aliases may not
|
||||
have common linkage.</dd>
|
||||
|
||||
@ -843,7 +843,7 @@ define i32 @main() { <i>; i32()* </i>
|
||||
|
||||
<p>LLVM function declarations consist of the "<tt>declare</tt>" keyword, an
|
||||
optional <a href="#linkage">linkage type</a>, an optional
|
||||
<a href="#visibility">visibility style</a>, an optional
|
||||
<a href="#visibility">visibility style</a>, an optional
|
||||
<a href="#callingconv">calling convention</a>, a return type, an optional
|
||||
<a href="#paramattrs">parameter attribute</a> for the return type, a function
|
||||
name, a possibly empty list of arguments, an optional alignment, and an
|
||||
@ -1192,7 +1192,7 @@ target datalayout = "<i>layout specification</i>"
|
||||
location.</dd>
|
||||
|
||||
<dt><tt>p:<i>size</i>:<i>abi</i>:<i>pref</i></tt></dt>
|
||||
<dd>This specifies the <i>size</i> of a pointer and its <i>abi</i> and
|
||||
<dd>This specifies the <i>size</i> of a pointer and its <i>abi</i> and
|
||||
<i>preferred</i> alignments. All sizes are in bits. Specifying
|
||||
the <i>pref</i> alignment is optional. If omitted, the
|
||||
preceding <tt>:</tt> should be omitted too.</dd>
|
||||
@ -1202,11 +1202,11 @@ target datalayout = "<i>layout specification</i>"
|
||||
<i>size</i>. The value of <i>size</i> must be in the range [1,2^23).</dd>
|
||||
|
||||
<dt><tt>v<i>size</i>:<i>abi</i>:<i>pref</i></tt></dt>
|
||||
<dd>This specifies the alignment for a vector type of a given bit
|
||||
<dd>This specifies the alignment for a vector type of a given bit
|
||||
<i>size</i>.</dd>
|
||||
|
||||
<dt><tt>f<i>size</i>:<i>abi</i>:<i>pref</i></tt></dt>
|
||||
<dd>This specifies the alignment for a floating point type of a given bit
|
||||
<dd>This specifies the alignment for a floating point type of a given bit
|
||||
<i>size</i>. The value of <i>size</i> must be either 32 (float) or 64
|
||||
(double).</dd>
|
||||
|
||||
@ -1222,7 +1222,7 @@ target datalayout = "<i>layout specification</i>"
|
||||
<dd>This specifies a set of native integer widths for the target CPU
|
||||
in bits. For example, it might contain "n32" for 32-bit PowerPC,
|
||||
"n32:64" for PowerPC 64, or "n8:16:32:64" for X86-64. Elements of
|
||||
this set are considered to support most general arithmetic
|
||||
this set are considered to support most general arithmetic
|
||||
operations efficiently.</dd>
|
||||
</dl>
|
||||
|
||||
@ -1616,16 +1616,16 @@ Classifications</a> </div>
|
||||
</tr><tr class="layout">
|
||||
<td class="left"><tt>float (i16 signext, i32 *) *
|
||||
</tt></td>
|
||||
<td class="left"><a href="#t_pointer">Pointer</a> to a function that takes
|
||||
an <tt>i16</tt> that should be sign extended and a
|
||||
<a href="#t_pointer">pointer</a> to <tt>i32</tt>, returning
|
||||
<td class="left"><a href="#t_pointer">Pointer</a> to a function that takes
|
||||
an <tt>i16</tt> that should be sign extended and a
|
||||
<a href="#t_pointer">pointer</a> to <tt>i32</tt>, returning
|
||||
<tt>float</tt>.
|
||||
</td>
|
||||
</tr><tr class="layout">
|
||||
<td class="left"><tt>i32 (i8*, ...)</tt></td>
|
||||
<td class="left">A vararg function that takes at least one
|
||||
<a href="#t_pointer">pointer</a> to <tt>i8 </tt> (char in C),
|
||||
which returns an integer. This is the signature for <tt>printf</tt> in
|
||||
<td class="left">A vararg function that takes at least one
|
||||
<a href="#t_pointer">pointer</a> to <tt>i8 </tt> (char in C),
|
||||
which returns an integer. This is the signature for <tt>printf</tt> in
|
||||
LLVM.
|
||||
</td>
|
||||
</tr><tr class="layout">
|
||||
@ -2054,9 +2054,9 @@ Unsafe:
|
||||
For example, if "%X" has a zero bit, then the output of the 'and' operation will
|
||||
always be a zero, no matter what the corresponding bit from the undef is. As
|
||||
such, it is unsafe to optimize or assume that the result of the and is undef.
|
||||
However, it is safe to assume that all bits of the undef could be 0, and
|
||||
optimize the and to 0. Likewise, it is safe to assume that all the bits of
|
||||
the undef operand to the or could be set, allowing the or to be folded to
|
||||
However, it is safe to assume that all bits of the undef could be 0, and
|
||||
optimize the and to 0. Likewise, it is safe to assume that all the bits of
|
||||
the undef operand to the or could be set, allowing the or to be folded to
|
||||
-1.</p>
|
||||
|
||||
<div class="doc_code">
|
||||
@ -2086,7 +2086,7 @@ the optimizer is allowed to assume that the undef operand could be the same as
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
%A = xor undef, undef
|
||||
|
||||
|
||||
%B = undef
|
||||
%C = xor %B, %B
|
||||
|
||||
@ -2137,7 +2137,7 @@ does not execute at all. This allows us to delete the divide and all code after
|
||||
it: since the undefined operation "can't happen", the optimizer can assume that
|
||||
it occurs in dead code.
|
||||
</p>
|
||||
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
a: store undef -> %X
|
||||
@ -2149,7 +2149,7 @@ b: unreachable
|
||||
</div>
|
||||
|
||||
<p>These examples reiterate the fdiv example: a store "of" an undefined value
|
||||
can be assumed to not have any effect: we can assume that the value is
|
||||
can be assumed to not have any effect: we can assume that the value is
|
||||
overwritten with bits that happen to match what was already there. However, a
|
||||
store "to" an undefined location could clobber arbitrary memory, therefore, it
|
||||
has undefined behavior.</p>
|
||||
@ -2166,7 +2166,7 @@ has undefined behavior.</p>
|
||||
<p>The '<tt>blockaddress</tt>' constant computes the address of the specified
|
||||
basic block in the specified function, and always has an i8* type. Taking
|
||||
the address of the entry block is illegal.</p>
|
||||
|
||||
|
||||
<p>This value only has defined behavior when used as an operand to the
|
||||
'<a href="#i_indirectbr"><tt>indirectbr</tt></a>' instruction or for comparisons
|
||||
against null. Pointer equality tests between labels addresses is undefined
|
||||
@ -2175,7 +2175,7 @@ has undefined behavior.</p>
|
||||
pointer sized value as long as the bits are not inspected. This allows
|
||||
<tt>ptrtoint</tt> and arithmetic to be performed on these values so long as
|
||||
the original value is reconstituted before the <tt>indirectbr</tt>.</p>
|
||||
|
||||
|
||||
<p>Finally, some targets may provide defined semantics when
|
||||
using the value as the operand to an inline assembly, but that is target
|
||||
specific.
|
||||
@ -2703,7 +2703,7 @@ IfUnequal:
|
||||
rest of the arguments indicate the full set of possible destinations that the
|
||||
address may point to. Blocks are allowed to occur multiple times in the
|
||||
destination list, though this isn't particularly useful.</p>
|
||||
|
||||
|
||||
<p>This destination list is required so that dataflow analysis has an accurate
|
||||
understanding of the CFG.</p>
|
||||
|
||||
@ -3060,7 +3060,7 @@ Instruction</a> </div>
|
||||
<p>The two arguments to the '<tt>mul</tt>' instruction must
|
||||
be <a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of
|
||||
integer values. Both arguments must have identical types.</p>
|
||||
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The value produced is the integer product of the two operands.</p>
|
||||
|
||||
@ -3132,7 +3132,7 @@ Instruction</a> </div>
|
||||
<p>The '<tt>udiv</tt>' instruction returns the quotient of its two operands.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The two arguments to the '<tt>udiv</tt>' instruction must be
|
||||
<p>The two arguments to the '<tt>udiv</tt>' instruction must be
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
values. Both arguments must have identical types.</p>
|
||||
|
||||
@ -3167,7 +3167,7 @@ Instruction</a> </div>
|
||||
<p>The '<tt>sdiv</tt>' instruction returns the quotient of its two operands.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The two arguments to the '<tt>sdiv</tt>' instruction must be
|
||||
<p>The two arguments to the '<tt>sdiv</tt>' instruction must be
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
values. Both arguments must have identical types.</p>
|
||||
|
||||
@ -3238,7 +3238,7 @@ Instruction</a> </div>
|
||||
division of its two arguments.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The two arguments to the '<tt>urem</tt>' instruction must be
|
||||
<p>The two arguments to the '<tt>urem</tt>' instruction must be
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
values. Both arguments must have identical types.</p>
|
||||
|
||||
@ -3278,7 +3278,7 @@ Instruction</a> </div>
|
||||
elements must be integers.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The two arguments to the '<tt>srem</tt>' instruction must be
|
||||
<p>The two arguments to the '<tt>srem</tt>' instruction must be
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
values. Both arguments must have identical types.</p>
|
||||
|
||||
@ -3373,7 +3373,7 @@ Instruction</a> </div>
|
||||
<p>Both arguments to the '<tt>shl</tt>' instruction must be the
|
||||
same <a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of
|
||||
integer type. '<tt>op2</tt>' is treated as an unsigned value.</p>
|
||||
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The value produced is <tt>op1</tt> * 2<sup><tt>op2</tt></sup> mod
|
||||
2<sup>n</sup>, where <tt>n</tt> is the width of the result. If <tt>op2</tt>
|
||||
@ -3409,7 +3409,7 @@ Instruction</a> </div>
|
||||
operand shifted to the right a specified number of bits with zero fill.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>Both arguments to the '<tt>lshr</tt>' instruction must be the same
|
||||
<p>Both arguments to the '<tt>lshr</tt>' instruction must be the same
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
type. '<tt>op2</tt>' is treated as an unsigned value.</p>
|
||||
|
||||
@ -3449,7 +3449,7 @@ Instruction</a> </div>
|
||||
extension.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>Both arguments to the '<tt>ashr</tt>' instruction must be the same
|
||||
<p>Both arguments to the '<tt>ashr</tt>' instruction must be the same
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
type. '<tt>op2</tt>' is treated as an unsigned value.</p>
|
||||
|
||||
@ -3489,7 +3489,7 @@ Instruction</a> </div>
|
||||
operands.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The two arguments to the '<tt>and</tt>' instruction must be
|
||||
<p>The two arguments to the '<tt>and</tt>' instruction must be
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
values. Both arguments must have identical types.</p>
|
||||
|
||||
@ -3548,7 +3548,7 @@ Instruction</a> </div>
|
||||
two operands.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The two arguments to the '<tt>or</tt>' instruction must be
|
||||
<p>The two arguments to the '<tt>or</tt>' instruction must be
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
values. Both arguments must have identical types.</p>
|
||||
|
||||
@ -3611,7 +3611,7 @@ Instruction</a> </div>
|
||||
complement" operation, which is the "~" operator in C.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The two arguments to the '<tt>xor</tt>' instruction must be
|
||||
<p>The two arguments to the '<tt>xor</tt>' instruction must be
|
||||
<a href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
values. Both arguments must have identical types.</p>
|
||||
|
||||
@ -3659,7 +3659,7 @@ Instruction</a> </div>
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<div class="doc_subsection">
|
||||
<a name="vectorops">Vector Operations</a>
|
||||
</div>
|
||||
|
||||
@ -3782,20 +3782,20 @@ Instruction</a> </div>
|
||||
|
||||
<h5>Example:</h5>
|
||||
<pre>
|
||||
<result> = shufflevector <4 x i32> %v1, <4 x i32> %v2,
|
||||
<result> = shufflevector <4 x i32> %v1, <4 x i32> %v2,
|
||||
<4 x i32> <i32 0, i32 4, i32 1, i32 5> <i>; yields <4 x i32></i>
|
||||
<result> = shufflevector <4 x i32> %v1, <4 x i32> undef,
|
||||
<result> = shufflevector <4 x i32> %v1, <4 x i32> undef,
|
||||
<4 x i32> <i32 0, i32 1, i32 2, i32 3> <i>; yields <4 x i32></i> - Identity shuffle.
|
||||
<result> = shufflevector <8 x i32> %v1, <8 x i32> undef,
|
||||
<result> = shufflevector <8 x i32> %v1, <8 x i32> undef,
|
||||
<4 x i32> <i32 0, i32 1, i32 2, i32 3> <i>; yields <4 x i32></i>
|
||||
<result> = shufflevector <4 x i32> %v1, <4 x i32> %v2,
|
||||
<result> = shufflevector <4 x i32> %v1, <4 x i32> %v2,
|
||||
<8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7 > <i>; yields <8 x i32></i>
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<div class="doc_subsection">
|
||||
<a name="aggregateops">Aggregate Operations</a>
|
||||
</div>
|
||||
|
||||
@ -3880,7 +3880,7 @@ Instruction</a> </div>
|
||||
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<div class="doc_subsection">
|
||||
<a name="memoryops">Memory Access and Addressing Operations</a>
|
||||
</div>
|
||||
|
||||
@ -4243,15 +4243,15 @@ entry:
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
<p>The '<tt>zext</tt>' instruction zero extends its operand to type
|
||||
<p>The '<tt>zext</tt>' instruction zero extends its operand to type
|
||||
<tt>ty2</tt>.</p>
|
||||
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The '<tt>zext</tt>' instruction takes a value to cast, which must be of
|
||||
<p>The '<tt>zext</tt>' instruction takes a value to cast, which must be of
|
||||
<a href="#t_integer">integer</a> type, and a type to cast it to, which must
|
||||
also be of <a href="#t_integer">integer</a> type. The bit size of the
|
||||
<tt>value</tt> must be smaller than the bit size of the destination type,
|
||||
<tt>value</tt> must be smaller than the bit size of the destination type,
|
||||
<tt>ty2</tt>.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
@ -4283,10 +4283,10 @@ entry:
|
||||
<p>The '<tt>sext</tt>' sign extends <tt>value</tt> to the type <tt>ty2</tt>.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The '<tt>sext</tt>' instruction takes a value to cast, which must be of
|
||||
<p>The '<tt>sext</tt>' instruction takes a value to cast, which must be of
|
||||
<a href="#t_integer">integer</a> type, and a type to cast it to, which must
|
||||
also be of <a href="#t_integer">integer</a> type. The bit size of the
|
||||
<tt>value</tt> must be smaller than the bit size of the destination type,
|
||||
<tt>value</tt> must be smaller than the bit size of the destination type,
|
||||
<tt>ty2</tt>.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
@ -4324,12 +4324,12 @@ entry:
|
||||
<p>The '<tt>fptrunc</tt>' instruction takes a <a href="#t_floating">floating
|
||||
point</a> value to cast and a <a href="#t_floating">floating point</a> type
|
||||
to cast it to. The size of <tt>value</tt> must be larger than the size of
|
||||
<tt>ty2</tt>. This implies that <tt>fptrunc</tt> cannot be used to make a
|
||||
<tt>ty2</tt>. This implies that <tt>fptrunc</tt> cannot be used to make a
|
||||
<i>no-op cast</i>.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>fptrunc</tt>' instruction truncates a <tt>value</tt> from a larger
|
||||
<a href="#t_floating">floating point</a> type to a smaller
|
||||
<a href="#t_floating">floating point</a> type to a smaller
|
||||
<a href="#t_floating">floating point</a> type. If the value cannot fit
|
||||
within the destination type, <tt>ty2</tt>, then the results are
|
||||
undefined.</p>
|
||||
@ -4358,7 +4358,7 @@ entry:
|
||||
floating point value.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The '<tt>fpext</tt>' instruction takes a
|
||||
<p>The '<tt>fpext</tt>' instruction takes a
|
||||
<a href="#t_floating">floating point</a> <tt>value</tt> to cast, and
|
||||
a <a href="#t_floating">floating point</a> type to cast it to. The source
|
||||
type must be smaller than the destination type.</p>
|
||||
@ -4401,7 +4401,7 @@ entry:
|
||||
vector integer type with the same number of elements as <tt>ty</tt></p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>fptoui</tt>' instruction converts its
|
||||
<p>The '<tt>fptoui</tt>' instruction converts its
|
||||
<a href="#t_floating">floating point</a> operand into the nearest (rounding
|
||||
towards zero) unsigned integer value. If the value cannot fit
|
||||
in <tt>ty2</tt>, the results are undefined.</p>
|
||||
@ -4427,7 +4427,7 @@ entry:
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
<p>The '<tt>fptosi</tt>' instruction converts
|
||||
<p>The '<tt>fptosi</tt>' instruction converts
|
||||
<a href="#t_floating">floating point</a> <tt>value</tt> to
|
||||
type <tt>ty2</tt>.</p>
|
||||
|
||||
@ -4439,7 +4439,7 @@ entry:
|
||||
vector integer type with the same number of elements as <tt>ty</tt></p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The '<tt>fptosi</tt>' instruction converts its
|
||||
<p>The '<tt>fptosi</tt>' instruction converts its
|
||||
<a href="#t_floating">floating point</a> operand into the nearest (rounding
|
||||
towards zero) signed integer value. If the value cannot fit in <tt>ty2</tt>,
|
||||
the results are undefined.</p>
|
||||
@ -4636,7 +4636,7 @@ entry:
|
||||
<pre>
|
||||
%X = bitcast i8 255 to i8 <i>; yields i8 :-1</i>
|
||||
%Y = bitcast i32* %x to sint* <i>; yields sint*:%x</i>
|
||||
%Z = bitcast <2 x int> %V to i64; <i>; yields i64: %V</i>
|
||||
%Z = bitcast <2 x int> %V to i64; <i>; yields i64: %V</i>
|
||||
</pre>
|
||||
|
||||
</div>
|
||||
@ -4696,11 +4696,11 @@ entry:
|
||||
result, as follows:</p>
|
||||
|
||||
<ol>
|
||||
<li><tt>eq</tt>: yields <tt>true</tt> if the operands are equal,
|
||||
<li><tt>eq</tt>: yields <tt>true</tt> if the operands are equal,
|
||||
<tt>false</tt> otherwise. No sign interpretation is necessary or
|
||||
performed.</li>
|
||||
|
||||
<li><tt>ne</tt>: yields <tt>true</tt> if the operands are unequal,
|
||||
<li><tt>ne</tt>: yields <tt>true</tt> if the operands are unequal,
|
||||
<tt>false</tt> otherwise. No sign interpretation is necessary or
|
||||
performed.</li>
|
||||
|
||||
@ -4817,42 +4817,42 @@ entry:
|
||||
<ol>
|
||||
<li><tt>false</tt>: always yields <tt>false</tt>, regardless of operands.</li>
|
||||
|
||||
<li><tt>oeq</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<li><tt>oeq</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<tt>op1</tt> is equal to <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>ogt</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<tt>op1</tt> is greather than <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>oge</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<li><tt>oge</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<tt>op1</tt> is greater than or equal to <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>olt</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<li><tt>olt</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<tt>op1</tt> is less than <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>ole</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<li><tt>ole</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<tt>op1</tt> is less than or equal to <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>one</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<li><tt>one</tt>: yields <tt>true</tt> if both operands are not a QNAN and
|
||||
<tt>op1</tt> is not equal to <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>ord</tt>: yields <tt>true</tt> if both operands are not a QNAN.</li>
|
||||
|
||||
<li><tt>ueq</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<li><tt>ueq</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<tt>op1</tt> is equal to <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>ugt</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<li><tt>ugt</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<tt>op1</tt> is greater than <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>uge</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<li><tt>uge</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<tt>op1</tt> is greater than or equal to <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>ult</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<li><tt>ult</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<tt>op1</tt> is less than <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>ule</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<li><tt>ule</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<tt>op1</tt> is less than or equal to <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>une</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<li><tt>une</tt>: yields <tt>true</tt> if either operand is a QNAN or
|
||||
<tt>op1</tt> is not equal to <tt>op2</tt>.</li>
|
||||
|
||||
<li><tt>uno</tt>: yields <tt>true</tt> if either operand is a QNAN.</li>
|
||||
@ -5144,7 +5144,7 @@ freestanding environments and non-C-based langauges.</p>
|
||||
suffix is required. Because the argument's type is matched against the return
|
||||
type, it does not require its own name suffix.</p>
|
||||
|
||||
<p>To learn how to add an intrinsic function, please see the
|
||||
<p>To learn how to add an intrinsic function, please see the
|
||||
<a href="ExtendingLLVM.html">Extending LLVM Guide</a>.</p>
|
||||
|
||||
</div>
|
||||
@ -6579,11 +6579,11 @@ LLVM</a>.</p>
|
||||
<ul>
|
||||
<li><tt>ll</tt>: All loads before the barrier must complete before any load
|
||||
after the barrier begins.</li>
|
||||
<li><tt>ls</tt>: All loads before the barrier must complete before any
|
||||
<li><tt>ls</tt>: All loads before the barrier must complete before any
|
||||
store after the barrier begins.</li>
|
||||
<li><tt>ss</tt>: All stores before the barrier must complete before any
|
||||
<li><tt>ss</tt>: All stores before the barrier must complete before any
|
||||
store after the barrier begins.</li>
|
||||
<li><tt>sl</tt>: All stores before the barrier must complete before any
|
||||
<li><tt>sl</tt>: All stores before the barrier must complete before any
|
||||
load after the barrier begins.</li>
|
||||
</ul>
|
||||
|
||||
@ -6796,7 +6796,7 @@ LLVM</a>.</p>
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
<p>This intrinsic subtracts <tt>delta</tt> to the value stored in memory at
|
||||
<p>This intrinsic subtracts <tt>delta</tt> to the value stored in memory at
|
||||
<tt>ptr</tt>. It yields the original value at <tt>ptr</tt>.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
@ -6952,7 +6952,7 @@ LLVM</a>.</p>
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
<p>These intrinsics takes the signed or unsigned minimum or maximum of
|
||||
<p>These intrinsics takes the signed or unsigned minimum or maximum of
|
||||
<tt>delta</tt> and the value stored in memory at <tt>ptr</tt>. It yields the
|
||||
original value at <tt>ptr</tt>.</p>
|
||||
|
||||
@ -7262,24 +7262,44 @@ LLVM</a>.</p>
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
<p>The <tt>llvm.objectsize</tt> intrinsic returns the constant number of bytes
|
||||
from <tt>ptr</tt> to the end of the object <tt>ptr</tt> points to if it
|
||||
can deduce this at compile time. If there are any side-effects in evaluating
|
||||
the argument or it cannot deduce which objects <tt>ptr</tt> points to at compile
|
||||
time the intrinsic returns <tt>(size_t) -1</tt> for <tt>type</tt> 0
|
||||
or 1 and <tt>(size_t) 0</tt> for <tt>type</tt> 2 or 3.</p>
|
||||
<p>The <tt>llvm.objectsize</tt> intrinsic is designed to provide information
|
||||
to the optimizers to either discover at compile time either a) when an
|
||||
operation like memcpy will either overflow a buffer that corresponds to
|
||||
an object, or b) to determine that a runtime check for overflow isn't
|
||||
necessary. An object in this context means an allocation of a
|
||||
specific <a href="#typesystem">type</a>.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
<p>The <tt>llvm.objectsize</tt> intrinsic takes two arguments. The first
|
||||
argument is a pointer to the object <tt>ptr</tt> and an integer <tt>type</tt>.
|
||||
<tt>type</tt> is an integer ranging from 0 to 3. The lsb corresponds to
|
||||
a return value based on whole objects, the second bit whether or not we
|
||||
return the maximum or minimum remaining bytes computed.</p>
|
||||
argument is a pointer to the object <tt>ptr</tt>. The second argument
|
||||
is an integer <tt>type</tt> which ranges from 0 to 3. The first bit in
|
||||
the type corresponds to a return value based on whole objects,
|
||||
and the second bit whether or not we return the maximum or minimum
|
||||
remaining bytes computed.</p>
|
||||
<table class="layout">
|
||||
<tr class="layout">
|
||||
<td class="left"><tt>00</tt></td>
|
||||
<td class="left">whole object, maximum number of bytes</td>
|
||||
</tr>
|
||||
<tr class="layout">
|
||||
<td class="left"><tt>01</tt></td>
|
||||
<td class="left">partial object, maximum number of bytes</td>
|
||||
</tr>
|
||||
<tr class="layout">
|
||||
<td class="left"><tt>10</tt></td>
|
||||
<td class="left">whole object, minimum number of bytes</td>
|
||||
</tr>
|
||||
<tr class="layout">
|
||||
<td class="left"><tt>11</tt></td>
|
||||
<td class="left">partial object, minimum number of bytes</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
<p>The <tt>llvm.objectsize</tt> intrinsic is lowered to either a constant
|
||||
representing the size of the object concerned or <tt>(size_t) -1</tt> if
|
||||
it cannot be determined at compile time.</p>
|
||||
representing the size of the object concerned or <tt>i32/i64 -1 or 0</tt>
|
||||
(depending on the <tt>type</tt> argument if the size cannot be determined
|
||||
at compile time.</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -7293,7 +7313,7 @@ LLVM</a>.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2009-11-30 09:03:53 +0100 (Mon, 30 Nov 2009) $
|
||||
Last modified: $Date: 2009-12-05 03:46:03 +0100 (Sat, 05 Dec 2009) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -100,7 +100,12 @@ install-ocamldoc: ocamldoc
|
||||
$(FIND) . -type f -exec \
|
||||
$(DataInstall) {} $(PROJ_docsdir)/ocamldoc/html \;
|
||||
|
||||
ocamldoc: regen-ocamldoc $(PROJ_OBJ_DIR)/ocamldoc.tar.gz
|
||||
ocamldoc: regen-ocamldoc
|
||||
$(Echo) Packaging ocamldoc documentation
|
||||
$(Verb) $(RM) -rf $(PROJ_OBJ_DIR)/ocamldoc.tar*
|
||||
$(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/ocamldoc.tar ocamldoc
|
||||
$(Verb) $(GZIP) $(PROJ_OBJ_DIR)/ocamldoc.tar
|
||||
$(Verb) $(CP) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_OBJ_DIR)/ocamldoc/html/
|
||||
|
||||
regen-ocamldoc:
|
||||
$(Echo) Building ocamldoc documentation
|
||||
@ -113,13 +118,6 @@ regen-ocamldoc:
|
||||
$(OCAMLDOC) -d $(PROJ_OBJ_DIR)/ocamldoc/html -sort -colorize-code -html \
|
||||
`$(FIND) $(LEVEL)/bindings/ocaml -name "*.odoc" -exec echo -load '{}' ';'`
|
||||
|
||||
$(PROJ_OBJ_DIR)/ocamldoc.tar.gz:
|
||||
$(Echo) Packaging ocamldoc documentation
|
||||
$(Verb) $(RM) -rf $@ $(PROJ_OBJ_DIR)/ocamldoc.tar
|
||||
$(Verb) $(TAR) cf $(PROJ_OBJ_DIR)/ocamldoc.tar ocamldoc
|
||||
$(Verb) $(GZIP) $(PROJ_OBJ_DIR)/ocamldoc.tar
|
||||
$(Verb) $(CP) $(PROJ_OBJ_DIR)/ocamldoc.tar.gz $(PROJ_OBJ_DIR)/ocamldoc/html/
|
||||
|
||||
uninstall-local::
|
||||
$(Echo) Uninstalling Documentation
|
||||
$(Verb) $(RM) -rf $(PROJ_docsdir)
|
||||
|
91
include/llvm/ADT/DeltaAlgorithm.h
Normal file
91
include/llvm/ADT/DeltaAlgorithm.h
Normal file
@ -0,0 +1,91 @@
|
||||
//===--- DeltaAlgorithm.h - A Set Minimization Algorithm -------*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_DELTAALGORITHM_H
|
||||
#define LLVM_ADT_DELTAALGORITHM_H
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// DeltaAlgorithm - Implements the delta debugging algorithm (A. Zeller '99)
|
||||
/// for minimizing arbitrary sets using a predicate function.
|
||||
///
|
||||
/// The result of the algorithm is a subset of the input change set which is
|
||||
/// guaranteed to satisfy the predicate, assuming that the input set did. For
|
||||
/// well formed predicates, the result set is guaranteed to be such that
|
||||
/// removing any single element would falsify the predicate.
|
||||
///
|
||||
/// For best results the predicate function *should* (but need not) satisfy
|
||||
/// certain properties, in particular:
|
||||
/// (1) The predicate should return false on an empty set and true on the full
|
||||
/// set.
|
||||
/// (2) If the predicate returns true for a set of changes, it should return
|
||||
/// true for all supersets of that set.
|
||||
///
|
||||
/// It is not an error to provide a predicate that does not satisfy these
|
||||
/// requirements, and the algorithm will generally produce reasonable
|
||||
/// results. However, it may run substantially more tests than with a good
|
||||
/// predicate.
|
||||
class DeltaAlgorithm {
|
||||
public:
|
||||
typedef unsigned change_ty;
|
||||
// FIXME: Use a decent data structure.
|
||||
typedef std::set<change_ty> changeset_ty;
|
||||
typedef std::vector<changeset_ty> changesetlist_ty;
|
||||
|
||||
private:
|
||||
/// Cache of failed test results. Successful test results are never cached
|
||||
/// since we always reduce following a success.
|
||||
std::set<changeset_ty> FailedTestsCache;
|
||||
|
||||
/// GetTestResult - Get the test result for the \arg Changes from the
|
||||
/// cache, executing the test if necessary.
|
||||
///
|
||||
/// \param Changes - The change set to test.
|
||||
/// \return - The test result.
|
||||
bool GetTestResult(const changeset_ty &Changes);
|
||||
|
||||
/// Split - Partition a set of changes \arg Sinto one or two subsets.
|
||||
void Split(const changeset_ty &S, changesetlist_ty &Res);
|
||||
|
||||
/// Delta - Minimize a set of \arg Changes which has been partioned into
|
||||
/// smaller sets, by attempting to remove individual subsets.
|
||||
changeset_ty Delta(const changeset_ty &Changes,
|
||||
const changesetlist_ty &Sets);
|
||||
|
||||
/// Search - Search for a subset (or subsets) in \arg Sets which can be
|
||||
/// removed from \arg Changes while still satisfying the predicate.
|
||||
///
|
||||
/// \param Res - On success, a subset of Changes which satisfies the
|
||||
/// predicate.
|
||||
/// \return - True on success.
|
||||
bool Search(const changeset_ty &Changes, const changesetlist_ty &Sets,
|
||||
changeset_ty &Res);
|
||||
|
||||
protected:
|
||||
/// UpdatedSearchState - Callback used when the search state changes.
|
||||
virtual void UpdatedSearchState(const changeset_ty &Changes,
|
||||
const changesetlist_ty &Sets) {}
|
||||
|
||||
/// ExecuteOneTest - Execute a single test predicate on the change set \arg S.
|
||||
virtual bool ExecuteOneTest(const changeset_ty &S) = 0;
|
||||
|
||||
public:
|
||||
virtual ~DeltaAlgorithm();
|
||||
|
||||
/// Run - Minimize the set \arg Changes by executing \see ExecuteOneTest() on
|
||||
/// subsets of changes and returning the smallest set which still satisfies
|
||||
/// the test predicate.
|
||||
changeset_ty Run(const changeset_ty &Changes);
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -217,7 +217,8 @@ class DenseMap {
|
||||
|
||||
private:
|
||||
void CopyFrom(const DenseMap& other) {
|
||||
if (NumBuckets != 0 && (!KeyInfoT::isPod() || !ValueInfoT::isPod())) {
|
||||
if (NumBuckets != 0 &&
|
||||
(!isPodLike<KeyInfoT>::value || !isPodLike<ValueInfoT>::value)) {
|
||||
const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey();
|
||||
for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) {
|
||||
if (!KeyInfoT::isEqual(P->first, EmptyKey) &&
|
||||
@ -239,7 +240,7 @@ class DenseMap {
|
||||
Buckets = static_cast<BucketT*>(operator new(sizeof(BucketT) *
|
||||
other.NumBuckets));
|
||||
|
||||
if (KeyInfoT::isPod() && ValueInfoT::isPod())
|
||||
if (isPodLike<KeyInfoT>::value && isPodLike<ValueInfoT>::value)
|
||||
memcpy(Buckets, other.Buckets, other.NumBuckets * sizeof(BucketT));
|
||||
else
|
||||
for (size_t i = 0; i < other.NumBuckets; ++i) {
|
||||
|
@ -15,7 +15,7 @@
|
||||
#define LLVM_ADT_DENSEMAPINFO_H
|
||||
|
||||
#include "llvm/Support/PointerLikeTypeTraits.h"
|
||||
#include <utility>
|
||||
#include "llvm/Support/type_traits.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -25,7 +25,6 @@ struct DenseMapInfo {
|
||||
//static inline T getTombstoneKey();
|
||||
//static unsigned getHashValue(const T &Val);
|
||||
//static bool isEqual(const T &LHS, const T &RHS);
|
||||
//static bool isPod()
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for all pointers.
|
||||
@ -46,7 +45,6 @@ struct DenseMapInfo<T*> {
|
||||
(unsigned((uintptr_t)PtrVal) >> 9);
|
||||
}
|
||||
static bool isEqual(const T *LHS, const T *RHS) { return LHS == RHS; }
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for chars.
|
||||
@ -54,7 +52,6 @@ template<> struct DenseMapInfo<char> {
|
||||
static inline char getEmptyKey() { return ~0; }
|
||||
static inline char getTombstoneKey() { return ~0 - 1; }
|
||||
static unsigned getHashValue(const char& Val) { return Val * 37; }
|
||||
static bool isPod() { return true; }
|
||||
static bool isEqual(const char &LHS, const char &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
@ -65,7 +62,6 @@ template<> struct DenseMapInfo<unsigned> {
|
||||
static inline unsigned getEmptyKey() { return ~0; }
|
||||
static inline unsigned getTombstoneKey() { return ~0U - 1; }
|
||||
static unsigned getHashValue(const unsigned& Val) { return Val * 37; }
|
||||
static bool isPod() { return true; }
|
||||
static bool isEqual(const unsigned& LHS, const unsigned& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
@ -78,7 +74,6 @@ template<> struct DenseMapInfo<unsigned long> {
|
||||
static unsigned getHashValue(const unsigned long& Val) {
|
||||
return (unsigned)(Val * 37UL);
|
||||
}
|
||||
static bool isPod() { return true; }
|
||||
static bool isEqual(const unsigned long& LHS, const unsigned long& RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
@ -91,7 +86,6 @@ template<> struct DenseMapInfo<unsigned long long> {
|
||||
static unsigned getHashValue(const unsigned long long& Val) {
|
||||
return (unsigned)(Val * 37ULL);
|
||||
}
|
||||
static bool isPod() { return true; }
|
||||
static bool isEqual(const unsigned long long& LHS,
|
||||
const unsigned long long& RHS) {
|
||||
return LHS == RHS;
|
||||
@ -127,7 +121,6 @@ struct DenseMapInfo<std::pair<T, U> > {
|
||||
return (unsigned)key;
|
||||
}
|
||||
static bool isEqual(const Pair& LHS, const Pair& RHS) { return LHS == RHS; }
|
||||
static bool isPod() { return FirstInfo::isPod() && SecondInfo::isPod(); }
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
@ -60,7 +60,7 @@ class DenseSet {
|
||||
ValueT& operator*() { return I->first; }
|
||||
ValueT* operator->() { return &I->first; }
|
||||
|
||||
Iterator& operator++() { ++I; return *this; };
|
||||
Iterator& operator++() { ++I; return *this; }
|
||||
bool operator==(const Iterator& X) const { return I == X.I; }
|
||||
bool operator!=(const Iterator& X) const { return I != X.I; }
|
||||
};
|
||||
@ -73,7 +73,7 @@ class DenseSet {
|
||||
const ValueT& operator*() { return I->first; }
|
||||
const ValueT* operator->() { return &I->first; }
|
||||
|
||||
ConstIterator& operator++() { ++I; return *this; };
|
||||
ConstIterator& operator++() { ++I; return *this; }
|
||||
bool operator==(const ConstIterator& X) const { return I == X.I; }
|
||||
bool operator!=(const ConstIterator& X) const { return I != X.I; }
|
||||
};
|
||||
|
@ -211,9 +211,12 @@ template<typename T> struct DenseMapInfo<ImmutableList<T> > {
|
||||
static bool isEqual(ImmutableList<T> X1, ImmutableList<T> X2) {
|
||||
return X1 == X2;
|
||||
}
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
|
||||
template <typename T> struct isPodLike;
|
||||
template <typename T>
|
||||
struct isPodLike<ImmutableList<T> > { static const bool value = true; };
|
||||
|
||||
} // end llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -106,6 +106,12 @@ class PointerIntPair {
|
||||
bool operator>=(const PointerIntPair &RHS) const {return Value >= RHS.Value;}
|
||||
};
|
||||
|
||||
template <typename T> struct isPodLike;
|
||||
template<typename PointerTy, unsigned IntBits, typename IntType>
|
||||
struct isPodLike<PointerIntPair<PointerTy, IntBits, IntType> > {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
// Provide specialization of DenseMapInfo for PointerIntPair.
|
||||
template<typename PointerTy, unsigned IntBits, typename IntType>
|
||||
struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > {
|
||||
@ -125,7 +131,6 @@ struct DenseMapInfo<PointerIntPair<PointerTy, IntBits, IntType> > {
|
||||
return unsigned(IV) ^ unsigned(IV >> 9);
|
||||
}
|
||||
static bool isEqual(const Ty &LHS, const Ty &RHS) { return LHS == RHS; }
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
|
||||
// Teach SmallPtrSet that PointerIntPair is "basically a pointer".
|
||||
|
@ -46,20 +46,17 @@ namespace std {
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// SmallVectorImpl - This class consists of common code factored out of the
|
||||
/// SmallVector class to reduce code duplication based on the SmallVector 'N'
|
||||
/// template parameter.
|
||||
template <typename T>
|
||||
class SmallVectorImpl {
|
||||
/// SmallVectorBase - This is all the non-templated stuff common to all
|
||||
/// SmallVectors.
|
||||
class SmallVectorBase {
|
||||
protected:
|
||||
T *Begin, *End, *Capacity;
|
||||
void *BeginX, *EndX, *CapacityX;
|
||||
|
||||
// Allocate raw space for N elements of type T. If T has a ctor or dtor, we
|
||||
// don't want it to be automatically run, so we need to represent the space as
|
||||
// something else. An array of char would work great, but might not be
|
||||
// aligned sufficiently. Instead, we either use GCC extensions, or some
|
||||
// number of union instances for the space, which guarantee maximal alignment.
|
||||
protected:
|
||||
#ifdef __GNUC__
|
||||
typedef char U;
|
||||
U FirstEl __attribute__((aligned));
|
||||
@ -72,46 +69,65 @@ class SmallVectorImpl {
|
||||
} FirstEl;
|
||||
#endif
|
||||
// Space after 'FirstEl' is clobbered, do not add any instance vars after it.
|
||||
|
||||
protected:
|
||||
SmallVectorBase(size_t Size)
|
||||
: BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {}
|
||||
|
||||
/// isSmall - Return true if this is a smallvector which has not had dynamic
|
||||
/// memory allocated for it.
|
||||
bool isSmall() const {
|
||||
return BeginX == static_cast<const void*>(&FirstEl);
|
||||
}
|
||||
|
||||
|
||||
public:
|
||||
bool empty() const { return BeginX == EndX; }
|
||||
};
|
||||
|
||||
/// SmallVectorImpl - This class consists of common code factored out of the
|
||||
/// SmallVector class to reduce code duplication based on the SmallVector 'N'
|
||||
/// template parameter.
|
||||
template <typename T>
|
||||
class SmallVectorImpl : public SmallVectorBase {
|
||||
void setEnd(T *P) { EndX = P; }
|
||||
public:
|
||||
// Default ctor - Initialize to empty.
|
||||
explicit SmallVectorImpl(unsigned N)
|
||||
: Begin(reinterpret_cast<T*>(&FirstEl)),
|
||||
End(reinterpret_cast<T*>(&FirstEl)),
|
||||
Capacity(reinterpret_cast<T*>(&FirstEl)+N) {
|
||||
explicit SmallVectorImpl(unsigned N) : SmallVectorBase(N*sizeof(T)) {
|
||||
}
|
||||
|
||||
~SmallVectorImpl() {
|
||||
// Destroy the constructed elements in the vector.
|
||||
destroy_range(Begin, End);
|
||||
destroy_range(begin(), end());
|
||||
|
||||
// If this wasn't grown from the inline copy, deallocate the old space.
|
||||
if (!isSmall())
|
||||
operator delete(Begin);
|
||||
operator delete(begin());
|
||||
}
|
||||
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T value_type;
|
||||
typedef T* iterator;
|
||||
typedef const T* const_iterator;
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
|
||||
bool empty() const { return Begin == End; }
|
||||
size_type size() const { return End-Begin; }
|
||||
size_type max_size() const { return size_type(-1) / sizeof(T); }
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
|
||||
// forward iterator creation methods.
|
||||
iterator begin() { return Begin; }
|
||||
const_iterator begin() const { return Begin; }
|
||||
iterator end() { return End; }
|
||||
const_iterator end() const { return End; }
|
||||
iterator begin() { return (iterator)BeginX; }
|
||||
const_iterator begin() const { return (const_iterator)BeginX; }
|
||||
iterator end() { return (iterator)EndX; }
|
||||
const_iterator end() const { return (const_iterator)EndX; }
|
||||
private:
|
||||
iterator capacity_ptr() { return (iterator)CapacityX; }
|
||||
const_iterator capacity_ptr() const { return (const_iterator)CapacityX; }
|
||||
public:
|
||||
|
||||
// reverse iterator creation methods.
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
@ -119,14 +135,25 @@ class SmallVectorImpl {
|
||||
reverse_iterator rend() { return reverse_iterator(begin()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator(begin());}
|
||||
|
||||
|
||||
size_type size() const { return end()-begin(); }
|
||||
size_type max_size() const { return size_type(-1) / sizeof(T); }
|
||||
|
||||
/// capacity - Return the total number of elements in the currently allocated
|
||||
/// buffer.
|
||||
size_t capacity() const { return capacity_ptr() - begin(); }
|
||||
|
||||
/// data - Return a pointer to the vector's buffer, even if empty().
|
||||
pointer data() { return pointer(begin()); }
|
||||
/// data - Return a pointer to the vector's buffer, even if empty().
|
||||
const_pointer data() const { return const_pointer(begin()); }
|
||||
|
||||
reference operator[](unsigned idx) {
|
||||
assert(Begin + idx < End);
|
||||
return Begin[idx];
|
||||
assert(begin() + idx < end());
|
||||
return begin()[idx];
|
||||
}
|
||||
const_reference operator[](unsigned idx) const {
|
||||
assert(Begin + idx < End);
|
||||
return Begin[idx];
|
||||
assert(begin() + idx < end());
|
||||
return begin()[idx];
|
||||
}
|
||||
|
||||
reference front() {
|
||||
@ -144,10 +171,10 @@ class SmallVectorImpl {
|
||||
}
|
||||
|
||||
void push_back(const_reference Elt) {
|
||||
if (End < Capacity) {
|
||||
if (EndX < CapacityX) {
|
||||
Retry:
|
||||
new (End) T(Elt);
|
||||
++End;
|
||||
new (end()) T(Elt);
|
||||
setEnd(end()+1);
|
||||
return;
|
||||
}
|
||||
grow();
|
||||
@ -155,8 +182,8 @@ class SmallVectorImpl {
|
||||
}
|
||||
|
||||
void pop_back() {
|
||||
--End;
|
||||
End->~T();
|
||||
setEnd(end()-1);
|
||||
end()->~T();
|
||||
}
|
||||
|
||||
T pop_back_val() {
|
||||
@ -166,36 +193,36 @@ class SmallVectorImpl {
|
||||
}
|
||||
|
||||
void clear() {
|
||||
destroy_range(Begin, End);
|
||||
End = Begin;
|
||||
destroy_range(begin(), end());
|
||||
EndX = BeginX;
|
||||
}
|
||||
|
||||
void resize(unsigned N) {
|
||||
if (N < size()) {
|
||||
destroy_range(Begin+N, End);
|
||||
End = Begin+N;
|
||||
destroy_range(begin()+N, end());
|
||||
setEnd(begin()+N);
|
||||
} else if (N > size()) {
|
||||
if (unsigned(Capacity-Begin) < N)
|
||||
if (capacity() < N)
|
||||
grow(N);
|
||||
construct_range(End, Begin+N, T());
|
||||
End = Begin+N;
|
||||
construct_range(end(), begin()+N, T());
|
||||
setEnd(begin()+N);
|
||||
}
|
||||
}
|
||||
|
||||
void resize(unsigned N, const T &NV) {
|
||||
if (N < size()) {
|
||||
destroy_range(Begin+N, End);
|
||||
End = Begin+N;
|
||||
destroy_range(begin()+N, end());
|
||||
setEnd(begin()+N);
|
||||
} else if (N > size()) {
|
||||
if (unsigned(Capacity-Begin) < N)
|
||||
if (capacity() < N)
|
||||
grow(N);
|
||||
construct_range(End, Begin+N, NV);
|
||||
End = Begin+N;
|
||||
construct_range(end(), begin()+N, NV);
|
||||
setEnd(begin()+N);
|
||||
}
|
||||
}
|
||||
|
||||
void reserve(unsigned N) {
|
||||
if (unsigned(Capacity-Begin) < N)
|
||||
if (capacity() < N)
|
||||
grow(N);
|
||||
}
|
||||
|
||||
@ -207,38 +234,38 @@ class SmallVectorImpl {
|
||||
void append(in_iter in_start, in_iter in_end) {
|
||||
size_type NumInputs = std::distance(in_start, in_end);
|
||||
// Grow allocated space if needed.
|
||||
if (NumInputs > size_type(Capacity-End))
|
||||
if (NumInputs > size_type(capacity_ptr()-end()))
|
||||
grow(size()+NumInputs);
|
||||
|
||||
// Copy the new elements over.
|
||||
std::uninitialized_copy(in_start, in_end, End);
|
||||
End += NumInputs;
|
||||
std::uninitialized_copy(in_start, in_end, end());
|
||||
setEnd(end() + NumInputs);
|
||||
}
|
||||
|
||||
/// append - Add the specified range to the end of the SmallVector.
|
||||
///
|
||||
void append(size_type NumInputs, const T &Elt) {
|
||||
// Grow allocated space if needed.
|
||||
if (NumInputs > size_type(Capacity-End))
|
||||
if (NumInputs > size_type(capacity_ptr()-end()))
|
||||
grow(size()+NumInputs);
|
||||
|
||||
// Copy the new elements over.
|
||||
std::uninitialized_fill_n(End, NumInputs, Elt);
|
||||
End += NumInputs;
|
||||
std::uninitialized_fill_n(end(), NumInputs, Elt);
|
||||
setEnd(end() + NumInputs);
|
||||
}
|
||||
|
||||
void assign(unsigned NumElts, const T &Elt) {
|
||||
clear();
|
||||
if (unsigned(Capacity-Begin) < NumElts)
|
||||
if (capacity() < NumElts)
|
||||
grow(NumElts);
|
||||
End = Begin+NumElts;
|
||||
construct_range(Begin, End, Elt);
|
||||
setEnd(begin()+NumElts);
|
||||
construct_range(begin(), end(), Elt);
|
||||
}
|
||||
|
||||
iterator erase(iterator I) {
|
||||
iterator N = I;
|
||||
// Shift all elts down one.
|
||||
std::copy(I+1, End, I);
|
||||
std::copy(I+1, end(), I);
|
||||
// Drop the last elt.
|
||||
pop_back();
|
||||
return(N);
|
||||
@ -247,36 +274,36 @@ class SmallVectorImpl {
|
||||
iterator erase(iterator S, iterator E) {
|
||||
iterator N = S;
|
||||
// Shift all elts down.
|
||||
iterator I = std::copy(E, End, S);
|
||||
iterator I = std::copy(E, end(), S);
|
||||
// Drop the last elts.
|
||||
destroy_range(I, End);
|
||||
End = I;
|
||||
destroy_range(I, end());
|
||||
setEnd(I);
|
||||
return(N);
|
||||
}
|
||||
|
||||
iterator insert(iterator I, const T &Elt) {
|
||||
if (I == End) { // Important special case for empty vector.
|
||||
if (I == end()) { // Important special case for empty vector.
|
||||
push_back(Elt);
|
||||
return end()-1;
|
||||
}
|
||||
|
||||
if (End < Capacity) {
|
||||
if (EndX < CapacityX) {
|
||||
Retry:
|
||||
new (End) T(back());
|
||||
++End;
|
||||
new (end()) T(back());
|
||||
setEnd(end()+1);
|
||||
// Push everything else over.
|
||||
std::copy_backward(I, End-1, End);
|
||||
std::copy_backward(I, end()-1, end());
|
||||
*I = Elt;
|
||||
return I;
|
||||
}
|
||||
size_t EltNo = I-Begin;
|
||||
size_t EltNo = I-begin();
|
||||
grow();
|
||||
I = Begin+EltNo;
|
||||
I = begin()+EltNo;
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
|
||||
if (I == End) { // Important special case for empty vector.
|
||||
if (I == end()) { // Important special case for empty vector.
|
||||
append(NumToInsert, Elt);
|
||||
return end()-1;
|
||||
}
|
||||
@ -295,8 +322,8 @@ class SmallVectorImpl {
|
||||
// insertion. Since we already reserved space, we know that this won't
|
||||
// reallocate the vector.
|
||||
if (size_t(end()-I) >= NumToInsert) {
|
||||
T *OldEnd = End;
|
||||
append(End-NumToInsert, End);
|
||||
T *OldEnd = end();
|
||||
append(end()-NumToInsert, end());
|
||||
|
||||
// Copy the existing elements that get replaced.
|
||||
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
|
||||
@ -309,10 +336,10 @@ class SmallVectorImpl {
|
||||
// not inserting at the end.
|
||||
|
||||
// Copy over the elements that we're about to overwrite.
|
||||
T *OldEnd = End;
|
||||
End += NumToInsert;
|
||||
T *OldEnd = end();
|
||||
setEnd(end() + NumToInsert);
|
||||
size_t NumOverwritten = OldEnd-I;
|
||||
std::uninitialized_copy(I, OldEnd, End-NumOverwritten);
|
||||
std::uninitialized_copy(I, OldEnd, end()-NumOverwritten);
|
||||
|
||||
// Replace the overwritten part.
|
||||
std::fill_n(I, NumOverwritten, Elt);
|
||||
@ -324,7 +351,7 @@ class SmallVectorImpl {
|
||||
|
||||
template<typename ItTy>
|
||||
iterator insert(iterator I, ItTy From, ItTy To) {
|
||||
if (I == End) { // Important special case for empty vector.
|
||||
if (I == end()) { // Important special case for empty vector.
|
||||
append(From, To);
|
||||
return end()-1;
|
||||
}
|
||||
@ -344,8 +371,8 @@ class SmallVectorImpl {
|
||||
// insertion. Since we already reserved space, we know that this won't
|
||||
// reallocate the vector.
|
||||
if (size_t(end()-I) >= NumToInsert) {
|
||||
T *OldEnd = End;
|
||||
append(End-NumToInsert, End);
|
||||
T *OldEnd = end();
|
||||
append(end()-NumToInsert, end());
|
||||
|
||||
// Copy the existing elements that get replaced.
|
||||
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
|
||||
@ -358,10 +385,10 @@ class SmallVectorImpl {
|
||||
// not inserting at the end.
|
||||
|
||||
// Copy over the elements that we're about to overwrite.
|
||||
T *OldEnd = End;
|
||||
End += NumToInsert;
|
||||
T *OldEnd = end();
|
||||
setEnd(end() + NumToInsert);
|
||||
size_t NumOverwritten = OldEnd-I;
|
||||
std::uninitialized_copy(I, OldEnd, End-NumOverwritten);
|
||||
std::uninitialized_copy(I, OldEnd, end()-NumOverwritten);
|
||||
|
||||
// Replace the overwritten part.
|
||||
std::copy(From, From+NumOverwritten, I);
|
||||
@ -371,25 +398,11 @@ class SmallVectorImpl {
|
||||
return I;
|
||||
}
|
||||
|
||||
/// data - Return a pointer to the vector's buffer, even if empty().
|
||||
pointer data() {
|
||||
return pointer(Begin);
|
||||
}
|
||||
|
||||
/// data - Return a pointer to the vector's buffer, even if empty().
|
||||
const_pointer data() const {
|
||||
return const_pointer(Begin);
|
||||
}
|
||||
|
||||
const SmallVectorImpl &operator=(const SmallVectorImpl &RHS);
|
||||
|
||||
bool operator==(const SmallVectorImpl &RHS) const {
|
||||
if (size() != RHS.size()) return false;
|
||||
for (T *This = Begin, *That = RHS.Begin, *E = Begin+size();
|
||||
This != E; ++This, ++That)
|
||||
if (*This != *That)
|
||||
return false;
|
||||
return true;
|
||||
return std::equal(begin(), end(), RHS.begin());
|
||||
}
|
||||
bool operator!=(const SmallVectorImpl &RHS) const { return !(*this == RHS); }
|
||||
|
||||
@ -398,10 +411,6 @@ class SmallVectorImpl {
|
||||
RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
/// capacity - Return the total number of elements in the currently allocated
|
||||
/// buffer.
|
||||
size_t capacity() const { return Capacity - Begin; }
|
||||
|
||||
/// set_size - Set the array size to \arg N, which the current array must have
|
||||
/// enough capacity for.
|
||||
///
|
||||
@ -413,17 +422,10 @@ class SmallVectorImpl {
|
||||
/// which will only be overwritten.
|
||||
void set_size(unsigned N) {
|
||||
assert(N <= capacity());
|
||||
End = Begin + N;
|
||||
setEnd(begin() + N);
|
||||
}
|
||||
|
||||
private:
|
||||
/// isSmall - Return true if this is a smallvector which has not had dynamic
|
||||
/// memory allocated for it.
|
||||
bool isSmall() const {
|
||||
return static_cast<const void*>(Begin) ==
|
||||
static_cast<const void*>(&FirstEl);
|
||||
}
|
||||
|
||||
/// grow - double the size of the allocated memory, guaranteeing space for at
|
||||
/// least one more element or MinSize if specified.
|
||||
void grow(size_type MinSize = 0);
|
||||
@ -434,6 +436,9 @@ class SmallVectorImpl {
|
||||
}
|
||||
|
||||
void destroy_range(T *S, T *E) {
|
||||
// No need to do a destroy loop for POD's.
|
||||
if (isPodLike<T>::value) return;
|
||||
|
||||
while (S != E) {
|
||||
--E;
|
||||
E->~T();
|
||||
@ -444,7 +449,7 @@ class SmallVectorImpl {
|
||||
// Define this out-of-line to dissuade the C++ compiler from inlining it.
|
||||
template <typename T>
|
||||
void SmallVectorImpl<T>::grow(size_t MinSize) {
|
||||
size_t CurCapacity = Capacity-Begin;
|
||||
size_t CurCapacity = capacity();
|
||||
size_t CurSize = size();
|
||||
size_t NewCapacity = 2*CurCapacity;
|
||||
if (NewCapacity < MinSize)
|
||||
@ -452,22 +457,22 @@ void SmallVectorImpl<T>::grow(size_t MinSize) {
|
||||
T *NewElts = static_cast<T*>(operator new(NewCapacity*sizeof(T)));
|
||||
|
||||
// Copy the elements over.
|
||||
if (is_class<T>::value)
|
||||
std::uninitialized_copy(Begin, End, NewElts);
|
||||
if (isPodLike<T>::value)
|
||||
// Use memcpy for PODs: std::uninitialized_copy optimizes to memmove.
|
||||
memcpy(NewElts, begin(), CurSize * sizeof(T));
|
||||
else
|
||||
// Use memcpy for PODs (std::uninitialized_copy optimizes to memmove).
|
||||
memcpy(NewElts, Begin, CurSize * sizeof(T));
|
||||
std::uninitialized_copy(begin(), end(), NewElts);
|
||||
|
||||
// Destroy the original elements.
|
||||
destroy_range(Begin, End);
|
||||
destroy_range(begin(), end());
|
||||
|
||||
// If this wasn't grown from the inline copy, deallocate the old space.
|
||||
if (!isSmall())
|
||||
operator delete(Begin);
|
||||
operator delete(begin());
|
||||
|
||||
Begin = NewElts;
|
||||
End = NewElts+CurSize;
|
||||
Capacity = Begin+NewCapacity;
|
||||
setEnd(NewElts+CurSize);
|
||||
BeginX = NewElts;
|
||||
CapacityX = begin()+NewCapacity;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -476,35 +481,35 @@ void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
|
||||
|
||||
// We can only avoid copying elements if neither vector is small.
|
||||
if (!isSmall() && !RHS.isSmall()) {
|
||||
std::swap(Begin, RHS.Begin);
|
||||
std::swap(End, RHS.End);
|
||||
std::swap(Capacity, RHS.Capacity);
|
||||
std::swap(BeginX, RHS.BeginX);
|
||||
std::swap(EndX, RHS.EndX);
|
||||
std::swap(CapacityX, RHS.CapacityX);
|
||||
return;
|
||||
}
|
||||
if (RHS.size() > size_type(Capacity-Begin))
|
||||
if (RHS.size() > capacity())
|
||||
grow(RHS.size());
|
||||
if (size() > size_type(RHS.Capacity-RHS.begin()))
|
||||
if (size() > RHS.capacity())
|
||||
RHS.grow(size());
|
||||
|
||||
// Swap the shared elements.
|
||||
size_t NumShared = size();
|
||||
if (NumShared > RHS.size()) NumShared = RHS.size();
|
||||
for (unsigned i = 0; i != static_cast<unsigned>(NumShared); ++i)
|
||||
std::swap(Begin[i], RHS[i]);
|
||||
std::swap((*this)[i], RHS[i]);
|
||||
|
||||
// Copy over the extra elts.
|
||||
if (size() > RHS.size()) {
|
||||
size_t EltDiff = size() - RHS.size();
|
||||
std::uninitialized_copy(Begin+NumShared, End, RHS.End);
|
||||
RHS.End += EltDiff;
|
||||
destroy_range(Begin+NumShared, End);
|
||||
End = Begin+NumShared;
|
||||
std::uninitialized_copy(begin()+NumShared, end(), RHS.end());
|
||||
RHS.setEnd(RHS.end()+EltDiff);
|
||||
destroy_range(begin()+NumShared, end());
|
||||
setEnd(begin()+NumShared);
|
||||
} else if (RHS.size() > size()) {
|
||||
size_t EltDiff = RHS.size() - size();
|
||||
std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End);
|
||||
End += EltDiff;
|
||||
destroy_range(RHS.Begin+NumShared, RHS.End);
|
||||
RHS.End = RHS.Begin+NumShared;
|
||||
std::uninitialized_copy(RHS.begin()+NumShared, RHS.end(), end());
|
||||
setEnd(end() + EltDiff);
|
||||
destroy_range(RHS.begin()+NumShared, RHS.end());
|
||||
RHS.setEnd(RHS.begin()+NumShared);
|
||||
}
|
||||
}
|
||||
|
||||
@ -516,42 +521,42 @@ SmallVectorImpl<T>::operator=(const SmallVectorImpl<T> &RHS) {
|
||||
|
||||
// If we already have sufficient space, assign the common elements, then
|
||||
// destroy any excess.
|
||||
unsigned RHSSize = unsigned(RHS.size());
|
||||
unsigned CurSize = unsigned(size());
|
||||
size_t RHSSize = RHS.size();
|
||||
size_t CurSize = size();
|
||||
if (CurSize >= RHSSize) {
|
||||
// Assign common elements.
|
||||
iterator NewEnd;
|
||||
if (RHSSize)
|
||||
NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin);
|
||||
NewEnd = std::copy(RHS.begin(), RHS.begin()+RHSSize, begin());
|
||||
else
|
||||
NewEnd = Begin;
|
||||
NewEnd = begin();
|
||||
|
||||
// Destroy excess elements.
|
||||
destroy_range(NewEnd, End);
|
||||
destroy_range(NewEnd, end());
|
||||
|
||||
// Trim.
|
||||
End = NewEnd;
|
||||
setEnd(NewEnd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// If we have to grow to have enough elements, destroy the current elements.
|
||||
// This allows us to avoid copying them during the grow.
|
||||
if (unsigned(Capacity-Begin) < RHSSize) {
|
||||
if (capacity() < RHSSize) {
|
||||
// Destroy current elements.
|
||||
destroy_range(Begin, End);
|
||||
End = Begin;
|
||||
destroy_range(begin(), end());
|
||||
setEnd(begin());
|
||||
CurSize = 0;
|
||||
grow(RHSSize);
|
||||
} else if (CurSize) {
|
||||
// Otherwise, use assignment for the already-constructed elements.
|
||||
std::copy(RHS.Begin, RHS.Begin+CurSize, Begin);
|
||||
std::copy(RHS.begin(), RHS.begin()+CurSize, begin());
|
||||
}
|
||||
|
||||
// Copy construct the new elements in place.
|
||||
std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize);
|
||||
std::uninitialized_copy(RHS.begin()+CurSize, RHS.end(), begin()+CurSize);
|
||||
|
||||
// Set end.
|
||||
End = Begin+RHSSize;
|
||||
setEnd(begin()+RHSSize);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
//===----------------------------------------------------------------------===/
|
||||
//
|
||||
// This file implements the StringSwitch template, which mimics a switch()
|
||||
// statements whose cases are string literals.
|
||||
// statement whose cases are string literals.
|
||||
//
|
||||
//===----------------------------------------------------------------------===/
|
||||
#ifndef LLVM_ADT_STRINGSWITCH_H
|
||||
@ -18,7 +18,7 @@
|
||||
#include <cstring>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
||||
/// \brief A switch()-like statement whose cases are string literals.
|
||||
///
|
||||
/// The StringSwitch class is a simple form of a switch() statement that
|
||||
@ -35,48 +35,44 @@ namespace llvm {
|
||||
/// .Case("green", Green)
|
||||
/// .Case("blue", Blue)
|
||||
/// .Case("indigo", Indigo)
|
||||
/// .Case("violet", Violet)
|
||||
/// .Cases("violet", "purple", Violet)
|
||||
/// .Default(UnknownColor);
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
template<typename T, typename R = T>
|
||||
class StringSwitch {
|
||||
/// \brief The string we are matching.
|
||||
StringRef Str;
|
||||
|
||||
/// \brief The result of this switch statement, once known.
|
||||
T Result;
|
||||
|
||||
/// \brief Set true when the result of this switch is already known; in this
|
||||
/// case, Result is valid.
|
||||
bool ResultKnown;
|
||||
|
||||
|
||||
/// \brief The pointer to the result of this switch statement, once known,
|
||||
/// null before that.
|
||||
const T *Result;
|
||||
|
||||
public:
|
||||
explicit StringSwitch(StringRef Str)
|
||||
: Str(Str), ResultKnown(false) { }
|
||||
|
||||
explicit StringSwitch(StringRef Str)
|
||||
: Str(Str), Result(0) { }
|
||||
|
||||
template<unsigned N>
|
||||
StringSwitch& Case(const char (&S)[N], const T& Value) {
|
||||
if (!ResultKnown && N-1 == Str.size() &&
|
||||
if (!Result && N-1 == Str.size() &&
|
||||
(std::memcmp(S, Str.data(), N-1) == 0)) {
|
||||
Result = Value;
|
||||
ResultKnown = true;
|
||||
Result = &Value;
|
||||
}
|
||||
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
template<unsigned N0, unsigned N1>
|
||||
StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
|
||||
const T& Value) {
|
||||
return Case(S0, Value).Case(S1, Value);
|
||||
}
|
||||
|
||||
|
||||
template<unsigned N0, unsigned N1, unsigned N2>
|
||||
StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
|
||||
const char (&S2)[N2], const T& Value) {
|
||||
return Case(S0, Value).Case(S1, Value).Case(S2, Value);
|
||||
}
|
||||
|
||||
|
||||
template<unsigned N0, unsigned N1, unsigned N2, unsigned N3>
|
||||
StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
|
||||
const char (&S2)[N2], const char (&S3)[N3],
|
||||
@ -87,21 +83,21 @@ class StringSwitch {
|
||||
template<unsigned N0, unsigned N1, unsigned N2, unsigned N3, unsigned N4>
|
||||
StringSwitch& Cases(const char (&S0)[N0], const char (&S1)[N1],
|
||||
const char (&S2)[N2], const char (&S3)[N3],
|
||||
const char (&S4)[N4], const T& Value) {
|
||||
const char (&S4)[N4], const T& Value) {
|
||||
return Case(S0, Value).Case(S1, Value).Case(S2, Value).Case(S3, Value)
|
||||
.Case(S4, Value);
|
||||
}
|
||||
|
||||
T Default(const T& Value) {
|
||||
if (ResultKnown)
|
||||
return Result;
|
||||
|
||||
|
||||
R Default(const T& Value) const {
|
||||
if (Result)
|
||||
return *Result;
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
operator T() {
|
||||
assert(ResultKnown && "Fell off the end of a string-switch");
|
||||
return Result;
|
||||
|
||||
operator R() const {
|
||||
assert(Result && "Fell off the end of a string-switch");
|
||||
return *Result;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -250,6 +250,12 @@ class ValueMapCallbackVH : public CallbackVH {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT>
|
||||
struct isPodLike<ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> > {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename KeyT, typename ValueT, typename Config, typename ValueInfoT>
|
||||
struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> > {
|
||||
typedef ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> VH;
|
||||
@ -267,7 +273,6 @@ struct DenseMapInfo<ValueMapCallbackVH<KeyT, ValueT, Config, ValueInfoT> > {
|
||||
static bool isEqual(const VH &LHS, const VH &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
static bool isPod() { return false; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -643,7 +643,7 @@ struct ilist : public iplist<NodeTy> {
|
||||
|
||||
// Main implementation here - Insert for a node passed by value...
|
||||
iterator insert(iterator where, const NodeTy &val) {
|
||||
return insert(where, createNode(val));
|
||||
return insert(where, this->createNode(val));
|
||||
}
|
||||
|
||||
|
||||
|
@ -259,11 +259,9 @@ class AliasSetTracker {
|
||||
ASTCallbackVH(Value *V, AliasSetTracker *AST = 0);
|
||||
ASTCallbackVH &operator=(Value *V);
|
||||
};
|
||||
/// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that ASTCallbackVH
|
||||
/// is not a POD (it needs its destructor called).
|
||||
struct ASTCallbackVHDenseMapInfo : public DenseMapInfo<Value *> {
|
||||
static bool isPod() { return false; }
|
||||
};
|
||||
/// ASTCallbackVHDenseMapInfo - Traits to tell DenseMap that tell us how to
|
||||
/// compare and hash the value handle.
|
||||
struct ASTCallbackVHDenseMapInfo : public DenseMapInfo<Value *> {};
|
||||
|
||||
AliasAnalysis &AA;
|
||||
ilist<AliasSet> AliasSets;
|
||||
|
@ -197,7 +197,8 @@ namespace llvm {
|
||||
FlagProtected = 1 << 1,
|
||||
FlagFwdDecl = 1 << 2,
|
||||
FlagAppleBlock = 1 << 3,
|
||||
FlagBlockByrefStruct = 1 << 4
|
||||
FlagBlockByrefStruct = 1 << 4,
|
||||
FlagVirtual = 1 << 5
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -242,6 +243,9 @@ namespace llvm {
|
||||
bool isBlockByrefStruct() const {
|
||||
return (getFlags() & FlagBlockByrefStruct) != 0;
|
||||
}
|
||||
bool isVirtual() const {
|
||||
return (getFlags() & FlagVirtual) != 0;
|
||||
}
|
||||
|
||||
/// dump - print type.
|
||||
void dump() const;
|
||||
@ -366,6 +370,24 @@ namespace llvm {
|
||||
/// compile unit, like 'static' in C.
|
||||
unsigned isLocalToUnit() const { return getUnsignedField(9); }
|
||||
unsigned isDefinition() const { return getUnsignedField(10); }
|
||||
|
||||
unsigned getVirtuality() const {
|
||||
if (DbgNode->getNumElements() < 14)
|
||||
return 0;
|
||||
return getUnsignedField(11);
|
||||
}
|
||||
|
||||
unsigned getVirtualIndex() const {
|
||||
if (DbgNode->getNumElements() < 14)
|
||||
return 0;
|
||||
return getUnsignedField(12);
|
||||
}
|
||||
|
||||
DICompositeType getContainingType() const {
|
||||
assert (DbgNode->getNumElements() >= 14 && "Invalid type!");
|
||||
return getFieldAs<DICompositeType>(13);
|
||||
}
|
||||
|
||||
StringRef getFilename() const { return getCompileUnit().getFilename();}
|
||||
StringRef getDirectory() const { return getCompileUnit().getDirectory();}
|
||||
|
||||
@ -470,6 +492,7 @@ namespace llvm {
|
||||
|
||||
const Type *EmptyStructPtr; // "{}*".
|
||||
Function *DeclareFn; // llvm.dbg.declare
|
||||
Function *ValueFn; // llvm.dbg.value
|
||||
|
||||
DIFactory(const DIFactory &); // DO NOT IMPLEMENT
|
||||
void operator=(const DIFactory&); // DO NOT IMPLEMENT
|
||||
@ -565,7 +588,14 @@ namespace llvm {
|
||||
StringRef LinkageName,
|
||||
DICompileUnit CompileUnit, unsigned LineNo,
|
||||
DIType Type, bool isLocalToUnit,
|
||||
bool isDefinition);
|
||||
bool isDefinition,
|
||||
unsigned VK = 0,
|
||||
unsigned VIndex = 0,
|
||||
DIType = DIType());
|
||||
|
||||
/// CreateSubprogramDefinition - Create new subprogram descriptor for the
|
||||
/// given declaration.
|
||||
DISubprogram CreateSubprogramDefinition(DISubprogram &SPDeclaration);
|
||||
|
||||
/// CreateGlobalVariable - Create a new descriptor for the specified global.
|
||||
DIGlobalVariable
|
||||
@ -610,6 +640,13 @@ namespace llvm {
|
||||
Instruction *InsertDeclare(llvm::Value *Storage, DIVariable D,
|
||||
Instruction *InsertBefore);
|
||||
|
||||
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
Instruction *InsertDbgValueIntrinsic(llvm::Value *V, llvm::Value *Offset,
|
||||
DIVariable D, BasicBlock *InsertAtEnd);
|
||||
|
||||
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
Instruction *InsertDbgValueIntrinsic(llvm::Value *V, llvm::Value *Offset,
|
||||
DIVariable D, Instruction *InsertBefore);
|
||||
private:
|
||||
Constant *GetTagConstant(unsigned TAG);
|
||||
};
|
||||
|
@ -175,11 +175,11 @@ class IVUsers : public LoopPass {
|
||||
ScalarEvolution *SE;
|
||||
SmallPtrSet<Instruction*,16> Processed;
|
||||
|
||||
public:
|
||||
/// IVUses - A list of all tracked IV uses of induction variable expressions
|
||||
/// we are interested in.
|
||||
ilist<IVUsersOfOneStride> IVUses;
|
||||
|
||||
public:
|
||||
/// IVUsesByStride - A mapping from the strides in StrideOrder to the
|
||||
/// uses in IVUses.
|
||||
std::map<const SCEV *, IVUsersOfOneStride*> IVUsesByStride;
|
||||
|
@ -67,17 +67,17 @@ class LoopDependenceAnalysis : public LoopPass {
|
||||
/// created. The third argument is set to the pair found or created.
|
||||
bool findOrInsertDependencePair(Value*, Value*, DependencePair*&);
|
||||
|
||||
/// getLoops - Collect all loops of the loop-nest L a given SCEV is variant
|
||||
/// in.
|
||||
/// getLoops - Collect all loops of the loop nest L in which
|
||||
/// a given SCEV is variant.
|
||||
void getLoops(const SCEV*, DenseSet<const Loop*>*) const;
|
||||
|
||||
/// isLoopInvariant - True if a given SCEV is invariant in all loops of the
|
||||
/// loop-nest starting at the innermost loop L.
|
||||
/// loop nest starting at the innermost loop L.
|
||||
bool isLoopInvariant(const SCEV*) const;
|
||||
|
||||
/// isAffine - An SCEV is affine with respect to the loop-nest starting at
|
||||
/// isAffine - An SCEV is affine with respect to the loop nest starting at
|
||||
/// the innermost loop L if it is of the form A+B*X where A, B are invariant
|
||||
/// in the loop-nest and X is a induction variable in the loop-nest.
|
||||
/// in the loop nest and X is a induction variable in the loop nest.
|
||||
bool isAffine(const SCEV*) const;
|
||||
|
||||
/// TODO: doc
|
||||
@ -93,8 +93,8 @@ class LoopDependenceAnalysis : public LoopPass {
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
LoopDependenceAnalysis() : LoopPass(&ID) {}
|
||||
|
||||
/// isDependencePair - Check wether two values can possibly give rise to a
|
||||
/// data dependence: that is the case if both are instructions accessing
|
||||
/// isDependencePair - Check whether two values can possibly give rise to
|
||||
/// a data dependence: that is the case if both are instructions accessing
|
||||
/// memory and at least one of those accesses is a write.
|
||||
bool isDependencePair(const Value*, const Value*) const;
|
||||
|
||||
|
@ -568,7 +568,7 @@ class Loop : public LoopBase<BasicBlock, Loop> {
|
||||
|
||||
/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
|
||||
/// These are the blocks _outside of the current loop_ which are branched to.
|
||||
/// This assumes that loop is in canonical form.
|
||||
/// This assumes that loop exits are in canonical form.
|
||||
///
|
||||
void getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const;
|
||||
|
||||
@ -976,13 +976,6 @@ class LoopInfo : public FunctionPass {
|
||||
void removeBlock(BasicBlock *BB) {
|
||||
LI.removeBlock(BB);
|
||||
}
|
||||
|
||||
static bool isNotAlreadyContainedIn(const Loop *SubLoop,
|
||||
const Loop *ParentLoop) {
|
||||
return
|
||||
LoopInfoBase<BasicBlock, Loop>::isNotAlreadyContainedIn(SubLoop,
|
||||
ParentLoop);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -52,7 +52,7 @@ class LoopPass : public Pass {
|
||||
// LPPassManger as expected.
|
||||
void preparePassManager(PMStack &PMS);
|
||||
|
||||
/// Assign pass manager to manager this pass
|
||||
/// Assign pass manager to manage this pass
|
||||
virtual void assignPassManager(PMStack &PMS,
|
||||
PassManagerType PMT = PMT_LoopPassManager);
|
||||
|
||||
@ -73,7 +73,7 @@ class LoopPass : public Pass {
|
||||
/// cloneBasicBlockAnalysis - Clone analysis info associated with basic block.
|
||||
virtual void cloneBasicBlockAnalysis(BasicBlock *F, BasicBlock *T, Loop *L) {}
|
||||
|
||||
/// deletekAnalysisValue - Delete analysis info associated with value V.
|
||||
/// deleteAnalysisValue - Delete analysis info associated with value V.
|
||||
virtual void deleteAnalysisValue(Value *V, Loop *L) {}
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include "llvm/BasicBlock.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/ValueHandle.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
@ -31,6 +32,7 @@ namespace llvm {
|
||||
class MemoryDependenceAnalysis;
|
||||
class PredIteratorCache;
|
||||
class DominatorTree;
|
||||
class PHITransAddr;
|
||||
|
||||
/// MemDepResult - A memory dependence query can return one of three different
|
||||
/// answers, described below.
|
||||
@ -60,9 +62,9 @@ namespace llvm {
|
||||
/// this case, the load is loading an undef value or a store is the
|
||||
/// first store to (that part of) the allocation.
|
||||
/// 3. Dependence queries on calls return Def only when they are
|
||||
/// readonly calls with identical callees and no intervening
|
||||
/// clobbers. No validation is done that the operands to the calls
|
||||
/// are the same.
|
||||
/// readonly calls or memory use intrinsics with identical callees
|
||||
/// and no intervening clobbers. No validation is done that the
|
||||
/// operands to the calls are the same.
|
||||
Def,
|
||||
|
||||
/// NonLocal - This marker indicates that the query has no dependency in
|
||||
@ -130,6 +132,45 @@ namespace llvm {
|
||||
}
|
||||
};
|
||||
|
||||
/// NonLocalDepEntry - This is an entry in the NonLocalDepInfo cache, and an
|
||||
/// entry in the results set for a non-local query. For each BasicBlock (the
|
||||
/// BB entry) it keeps a MemDepResult and the (potentially phi translated)
|
||||
/// address that was live in the block.
|
||||
class NonLocalDepEntry {
|
||||
BasicBlock *BB;
|
||||
MemDepResult Result;
|
||||
WeakVH Address;
|
||||
public:
|
||||
NonLocalDepEntry(BasicBlock *bb, MemDepResult result, Value *address)
|
||||
: BB(bb), Result(result), Address(address) {}
|
||||
|
||||
// This is used for searches.
|
||||
NonLocalDepEntry(BasicBlock *bb) : BB(bb) {}
|
||||
|
||||
// BB is the sort key, it can't be changed.
|
||||
BasicBlock *getBB() const { return BB; }
|
||||
|
||||
void setResult(const MemDepResult &R, Value *Addr) {
|
||||
Result = R;
|
||||
Address = Addr;
|
||||
}
|
||||
|
||||
const MemDepResult &getResult() const { return Result; }
|
||||
|
||||
/// getAddress - Return the address of this pointer in this block. This can
|
||||
/// be different than the address queried for the non-local result because
|
||||
/// of phi translation. This returns null if the address was not available
|
||||
/// in a block (i.e. because phi translation failed) or if this is a cached
|
||||
/// result and that address was deleted.
|
||||
///
|
||||
/// The address is always null for a non-local 'call' dependence.
|
||||
Value *getAddress() const { return Address; }
|
||||
|
||||
bool operator<(const NonLocalDepEntry &RHS) const {
|
||||
return BB < RHS.BB;
|
||||
}
|
||||
};
|
||||
|
||||
/// MemoryDependenceAnalysis - This is an analysis that determines, for a
|
||||
/// given memory operation, what preceding memory operations it depends on.
|
||||
/// It builds on alias analysis information, and tries to provide a lazy,
|
||||
@ -151,7 +192,6 @@ namespace llvm {
|
||||
LocalDepMapType LocalDeps;
|
||||
|
||||
public:
|
||||
typedef std::pair<BasicBlock*, MemDepResult> NonLocalDepEntry;
|
||||
typedef std::vector<NonLocalDepEntry> NonLocalDepInfo;
|
||||
private:
|
||||
/// ValueIsLoadPair - This is a pair<Value*, bool> where the bool is true if
|
||||
@ -245,29 +285,6 @@ namespace llvm {
|
||||
BasicBlock *BB,
|
||||
SmallVectorImpl<NonLocalDepEntry> &Result);
|
||||
|
||||
/// GetPHITranslatedValue - Find an available version of the specified value
|
||||
/// PHI translated across the specified edge. If MemDep isn't able to
|
||||
/// satisfy this request, it returns null.
|
||||
Value *GetPHITranslatedValue(Value *V,
|
||||
BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const TargetData *TD) const;
|
||||
|
||||
/// GetAvailablePHITranslatedValue - Return the value computed by
|
||||
/// PHITranslatePointer if it dominates PredBB, otherwise return null.
|
||||
Value *GetAvailablePHITranslatedValue(Value *V,
|
||||
BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const TargetData *TD,
|
||||
const DominatorTree &DT) const;
|
||||
|
||||
/// InsertPHITranslatedPointer - Insert a computation of the PHI translated
|
||||
/// version of 'V' for the edge PredBB->CurBB into the end of the PredBB
|
||||
/// block. All newly created instructions are added to the NewInsts list.
|
||||
Value *InsertPHITranslatedPointer(Value *V,
|
||||
BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const TargetData *TD,
|
||||
const DominatorTree &DT,
|
||||
SmallVectorImpl<Instruction*> &NewInsts) const;
|
||||
|
||||
/// removeInstruction - Remove an instruction from the dependence analysis,
|
||||
/// updating the dependence of instructions that previously depended on it.
|
||||
void removeInstruction(Instruction *InstToRemove);
|
||||
@ -288,7 +305,7 @@ namespace llvm {
|
||||
MemDepResult getCallSiteDependencyFrom(CallSite C, bool isReadOnlyCall,
|
||||
BasicBlock::iterator ScanIt,
|
||||
BasicBlock *BB);
|
||||
bool getNonLocalPointerDepFromBB(Value *Pointer, uint64_t Size,
|
||||
bool getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, uint64_t Size,
|
||||
bool isLoad, BasicBlock *BB,
|
||||
SmallVectorImpl<NonLocalDepEntry> &Result,
|
||||
DenseMap<BasicBlock*, Value*> &Visited,
|
||||
|
121
include/llvm/Analysis/PHITransAddr.h
Normal file
121
include/llvm/Analysis/PHITransAddr.h
Normal file
@ -0,0 +1,121 @@
|
||||
//===- PHITransAddr.h - PHI Translation for Addresses -----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the PHITransAddr class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_PHITRANSADDR_H
|
||||
#define LLVM_ANALYSIS_PHITRANSADDR_H
|
||||
|
||||
#include "llvm/Instruction.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace llvm {
|
||||
class DominatorTree;
|
||||
class TargetData;
|
||||
|
||||
/// PHITransAddr - An address value which tracks and handles phi translation.
|
||||
/// As we walk "up" the CFG through predecessors, we need to ensure that the
|
||||
/// address we're tracking is kept up to date. For example, if we're analyzing
|
||||
/// an address of "&A[i]" and walk through the definition of 'i' which is a PHI
|
||||
/// node, we *must* phi translate i to get "&A[j]" or else we will analyze an
|
||||
/// incorrect pointer in the predecessor block.
|
||||
///
|
||||
/// This is designed to be a relatively small object that lives on the stack and
|
||||
/// is copyable.
|
||||
///
|
||||
class PHITransAddr {
|
||||
/// Addr - The actual address we're analyzing.
|
||||
Value *Addr;
|
||||
|
||||
/// TD - The target data we are playing with if known, otherwise null.
|
||||
const TargetData *TD;
|
||||
|
||||
/// InstInputs - The inputs for our symbolic address.
|
||||
SmallVector<Instruction*, 4> InstInputs;
|
||||
public:
|
||||
PHITransAddr(Value *addr, const TargetData *td) : Addr(addr), TD(td) {
|
||||
// If the address is an instruction, the whole thing is considered an input.
|
||||
if (Instruction *I = dyn_cast<Instruction>(Addr))
|
||||
InstInputs.push_back(I);
|
||||
}
|
||||
|
||||
Value *getAddr() const { return Addr; }
|
||||
|
||||
/// NeedsPHITranslationFromBlock - Return true if moving from the specified
|
||||
/// BasicBlock to its predecessors requires PHI translation.
|
||||
bool NeedsPHITranslationFromBlock(BasicBlock *BB) const {
|
||||
// We do need translation if one of our input instructions is defined in
|
||||
// this block.
|
||||
for (unsigned i = 0, e = InstInputs.size(); i != e; ++i)
|
||||
if (InstInputs[i]->getParent() == BB)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// IsPotentiallyPHITranslatable - If this needs PHI translation, return true
|
||||
/// if we have some hope of doing it. This should be used as a filter to
|
||||
/// avoid calling PHITranslateValue in hopeless situations.
|
||||
bool IsPotentiallyPHITranslatable() const;
|
||||
|
||||
/// PHITranslateValue - PHI translate the current address up the CFG from
|
||||
/// CurBB to Pred, updating our state the reflect any needed changes. This
|
||||
/// returns true on failure and sets Addr to null.
|
||||
bool PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB);
|
||||
|
||||
/// PHITranslateWithInsertion - PHI translate this value into the specified
|
||||
/// predecessor block, inserting a computation of the value if it is
|
||||
/// unavailable.
|
||||
///
|
||||
/// All newly created instructions are added to the NewInsts list. This
|
||||
/// returns null on failure.
|
||||
///
|
||||
Value *PHITranslateWithInsertion(BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const DominatorTree &DT,
|
||||
SmallVectorImpl<Instruction*> &NewInsts);
|
||||
|
||||
void dump() const;
|
||||
|
||||
/// Verify - Check internal consistency of this data structure. If the
|
||||
/// structure is valid, it returns true. If invalid, it prints errors and
|
||||
/// returns false.
|
||||
bool Verify() const;
|
||||
private:
|
||||
Value *PHITranslateSubExpr(Value *V, BasicBlock *CurBB, BasicBlock *PredBB);
|
||||
|
||||
|
||||
/// GetAvailablePHITranslatedSubExpr - Return the value computed by
|
||||
/// PHITranslateSubExpr if it dominates PredBB, otherwise return null.
|
||||
Value *GetAvailablePHITranslatedSubExpr(Value *V,
|
||||
BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const DominatorTree &DT) const;
|
||||
|
||||
/// InsertPHITranslatedSubExpr - Insert a computation of the PHI translated
|
||||
/// version of 'V' for the edge PredBB->CurBB into the end of the PredBB
|
||||
/// block. All newly created instructions are added to the NewInsts list.
|
||||
/// This returns null on failure.
|
||||
///
|
||||
Value *InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB,
|
||||
BasicBlock *PredBB, const DominatorTree &DT,
|
||||
SmallVectorImpl<Instruction*> &NewInsts);
|
||||
|
||||
/// AddAsInput - If the specified value is an instruction, add it as an input.
|
||||
Value *AddAsInput(Value *V) {
|
||||
// If V is an instruction, it is now an input.
|
||||
if (Instruction *VI = dyn_cast<Instruction>(V))
|
||||
InstInputs.push_back(VI);
|
||||
return V;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -92,6 +92,7 @@ namespace llvm {
|
||||
// file.
|
||||
//
|
||||
ModulePass *createProfileLoaderPass();
|
||||
extern const PassInfo *ProfileLoaderPassID;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
//
|
||||
|
@ -21,116 +21,228 @@
|
||||
#ifndef LLVM_ANALYSIS_PROFILEINFO_H
|
||||
#define LLVM_ANALYSIS_PROFILEINFO_H
|
||||
|
||||
#include "llvm/BasicBlock.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
class Function;
|
||||
class Pass;
|
||||
class raw_ostream;
|
||||
|
||||
class BasicBlock;
|
||||
class Function;
|
||||
class MachineBasicBlock;
|
||||
class MachineFunction;
|
||||
|
||||
// Helper for dumping edges to errs().
|
||||
raw_ostream& operator<<(raw_ostream &O, std::pair<const BasicBlock *, const BasicBlock *> E);
|
||||
raw_ostream& operator<<(raw_ostream &O, std::pair<const MachineBasicBlock *, const MachineBasicBlock *> E);
|
||||
|
||||
raw_ostream& operator<<(raw_ostream &O, const BasicBlock *BB);
|
||||
raw_ostream& operator<<(raw_ostream &O, const MachineBasicBlock *MBB);
|
||||
|
||||
raw_ostream& operator<<(raw_ostream &O, const Function *F);
|
||||
raw_ostream& operator<<(raw_ostream &O, const MachineFunction *MF);
|
||||
|
||||
/// ProfileInfo Class - This class holds and maintains profiling
|
||||
/// information for some unit of code.
|
||||
class ProfileInfo {
|
||||
template<class FType, class BType>
|
||||
class ProfileInfoT {
|
||||
public:
|
||||
// Types for handling profiling information.
|
||||
typedef std::pair<const BasicBlock*, const BasicBlock*> Edge;
|
||||
typedef std::pair<const BType*, const BType*> Edge;
|
||||
typedef std::pair<Edge, double> EdgeWeight;
|
||||
typedef std::map<Edge, double> EdgeWeights;
|
||||
typedef std::map<const BasicBlock*, double> BlockCounts;
|
||||
typedef std::map<const BType*, double> BlockCounts;
|
||||
typedef std::map<const BType*, const BType*> Path;
|
||||
|
||||
protected:
|
||||
// EdgeInformation - Count the number of times a transition between two
|
||||
// blocks is executed. As a special case, we also hold an edge from the
|
||||
// null BasicBlock to the entry block to indicate how many times the
|
||||
// function was entered.
|
||||
std::map<const Function*, EdgeWeights> EdgeInformation;
|
||||
std::map<const FType*, EdgeWeights> EdgeInformation;
|
||||
|
||||
// BlockInformation - Count the number of times a block is executed.
|
||||
std::map<const Function*, BlockCounts> BlockInformation;
|
||||
std::map<const FType*, BlockCounts> BlockInformation;
|
||||
|
||||
// FunctionInformation - Count the number of times a function is executed.
|
||||
std::map<const Function*, double> FunctionInformation;
|
||||
std::map<const FType*, double> FunctionInformation;
|
||||
|
||||
ProfileInfoT<MachineFunction, MachineBasicBlock> *MachineProfile;
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
virtual ~ProfileInfo(); // We want to be subclassed
|
||||
ProfileInfoT();
|
||||
~ProfileInfoT(); // We want to be subclassed
|
||||
|
||||
// MissingValue - The value that is returned for execution counts in case
|
||||
// no value is available.
|
||||
static const double MissingValue;
|
||||
|
||||
// getFunction() - Returns the Function for an Edge, checking for validity.
|
||||
static const Function* getFunction(Edge e) {
|
||||
static const FType* getFunction(Edge e) {
|
||||
if (e.first) {
|
||||
return e.first->getParent();
|
||||
} else if (e.second) {
|
||||
return e.second->getParent();
|
||||
}
|
||||
assert(0 && "Invalid ProfileInfo::Edge");
|
||||
return (const Function*)0;
|
||||
return (const FType*)0;
|
||||
}
|
||||
|
||||
// getEdge() - Creates an Edge from two BasicBlocks.
|
||||
static Edge getEdge(const BasicBlock *Src, const BasicBlock *Dest) {
|
||||
static Edge getEdge(const BType *Src, const BType *Dest) {
|
||||
return std::make_pair(Src, Dest);
|
||||
}
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
/// Profile Information Queries
|
||||
///
|
||||
double getExecutionCount(const Function *F);
|
||||
double getExecutionCount(const FType *F);
|
||||
|
||||
double getExecutionCount(const BasicBlock *BB);
|
||||
double getExecutionCount(const BType *BB);
|
||||
|
||||
void setExecutionCount(const BType *BB, double w);
|
||||
|
||||
void addExecutionCount(const BType *BB, double w);
|
||||
|
||||
double getEdgeWeight(Edge e) const {
|
||||
std::map<const Function*, EdgeWeights>::const_iterator J =
|
||||
typename std::map<const FType*, EdgeWeights>::const_iterator J =
|
||||
EdgeInformation.find(getFunction(e));
|
||||
if (J == EdgeInformation.end()) return MissingValue;
|
||||
|
||||
EdgeWeights::const_iterator I = J->second.find(e);
|
||||
typename EdgeWeights::const_iterator I = J->second.find(e);
|
||||
if (I == J->second.end()) return MissingValue;
|
||||
|
||||
return I->second;
|
||||
}
|
||||
|
||||
EdgeWeights &getEdgeWeights (const Function *F) {
|
||||
void setEdgeWeight(Edge e, double w) {
|
||||
DEBUG_WITH_TYPE("profile-info",
|
||||
errs() << "Creating Edge " << e
|
||||
<< " (weight: " << format("%.20g",w) << ")\n");
|
||||
EdgeInformation[getFunction(e)][e] = w;
|
||||
}
|
||||
|
||||
void addEdgeWeight(Edge e, double w);
|
||||
|
||||
EdgeWeights &getEdgeWeights (const FType *F) {
|
||||
return EdgeInformation[F];
|
||||
}
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
/// Analysis Update Methods
|
||||
///
|
||||
void removeBlock(const BasicBlock *BB) {
|
||||
std::map<const Function*, BlockCounts>::iterator J =
|
||||
BlockInformation.find(BB->getParent());
|
||||
if (J == BlockInformation.end()) return;
|
||||
void removeBlock(const BType *BB);
|
||||
|
||||
J->second.erase(BB);
|
||||
void removeEdge(Edge e);
|
||||
|
||||
void replaceEdge(const Edge &, const Edge &);
|
||||
|
||||
enum GetPathMode {
|
||||
GetPathToExit = 1,
|
||||
GetPathToValue = 2,
|
||||
GetPathToDest = 4,
|
||||
GetPathWithNewEdges = 8
|
||||
};
|
||||
|
||||
const BType *GetPath(const BType *Src, const BType *Dest,
|
||||
Path &P, unsigned Mode);
|
||||
|
||||
void divertFlow(const Edge &, const Edge &);
|
||||
|
||||
void splitEdge(const BType *FirstBB, const BType *SecondBB,
|
||||
const BType *NewBB, bool MergeIdenticalEdges = false);
|
||||
|
||||
void splitBlock(const BType *Old, const BType* New);
|
||||
|
||||
void splitBlock(const BType *BB, const BType* NewBB,
|
||||
BType *const *Preds, unsigned NumPreds);
|
||||
|
||||
void replaceAllUses(const BType *RmBB, const BType *DestBB);
|
||||
|
||||
void transfer(const FType *Old, const FType *New);
|
||||
|
||||
void repair(const FType *F);
|
||||
|
||||
void dump(FType *F = 0, bool real = true) {
|
||||
errs() << "**** This is ProfileInfo " << this << " speaking:\n";
|
||||
if (!real) {
|
||||
typename std::set<const FType*> Functions;
|
||||
|
||||
errs() << "Functions: \n";
|
||||
if (F) {
|
||||
errs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n";
|
||||
Functions.insert(F);
|
||||
} else {
|
||||
for (typename std::map<const FType*, double>::iterator fi = FunctionInformation.begin(),
|
||||
fe = FunctionInformation.end(); fi != fe; ++fi) {
|
||||
errs() << fi->first << "@" << format("%p",fi->first) << ": " << format("%.20g",fi->second) << "\n";
|
||||
Functions.insert(fi->first);
|
||||
}
|
||||
}
|
||||
|
||||
for (typename std::set<const FType*>::iterator FI = Functions.begin(), FE = Functions.end();
|
||||
FI != FE; ++FI) {
|
||||
const FType *F = *FI;
|
||||
typename std::map<const FType*, BlockCounts>::iterator bwi = BlockInformation.find(F);
|
||||
errs() << "BasicBlocks for Function " << F << ":\n";
|
||||
for (typename BlockCounts::const_iterator bi = bwi->second.begin(), be = bwi->second.end(); bi != be; ++bi) {
|
||||
errs() << bi->first << "@" << format("%p", bi->first) << ": " << format("%.20g",bi->second) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
for (typename std::set<const FType*>::iterator FI = Functions.begin(), FE = Functions.end();
|
||||
FI != FE; ++FI) {
|
||||
typename std::map<const FType*, EdgeWeights>::iterator ei = EdgeInformation.find(*FI);
|
||||
errs() << "Edges for Function " << ei->first << ":\n";
|
||||
for (typename EdgeWeights::iterator ewi = ei->second.begin(), ewe = ei->second.end();
|
||||
ewi != ewe; ++ewi) {
|
||||
errs() << ewi->first << ": " << format("%.20g",ewi->second) << "\n";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert(F && "No function given, this is not supported!");
|
||||
errs() << "Functions: \n";
|
||||
errs() << F << "@" << format("%p", F) << ": " << format("%.20g",getExecutionCount(F)) << "\n";
|
||||
|
||||
errs() << "BasicBlocks for Function " << F << ":\n";
|
||||
for (typename FType::const_iterator BI = F->begin(), BE = F->end();
|
||||
BI != BE; ++BI) {
|
||||
const BType *BB = &(*BI);
|
||||
errs() << BB << "@" << format("%p", BB) << ": " << format("%.20g",getExecutionCount(BB)) << "\n";
|
||||
}
|
||||
}
|
||||
errs() << "**** ProfileInfo " << this << ", over and out.\n";
|
||||
}
|
||||
|
||||
void removeEdge(Edge e) {
|
||||
std::map<const Function*, EdgeWeights>::iterator J =
|
||||
EdgeInformation.find(getFunction(e));
|
||||
if (J == EdgeInformation.end()) return;
|
||||
bool CalculateMissingEdge(const BType *BB, Edge &removed, bool assumeEmptyExit = false);
|
||||
|
||||
J->second.erase(e);
|
||||
bool EstimateMissingEdges(const BType *BB);
|
||||
|
||||
ProfileInfoT<MachineFunction, MachineBasicBlock> *MI() {
|
||||
if (MachineProfile == 0)
|
||||
MachineProfile = new ProfileInfoT<MachineFunction, MachineBasicBlock>();
|
||||
return MachineProfile;
|
||||
}
|
||||
|
||||
void splitEdge(const BasicBlock *FirstBB, const BasicBlock *SecondBB,
|
||||
const BasicBlock *NewBB, bool MergeIdenticalEdges = false);
|
||||
|
||||
void replaceAllUses(const BasicBlock *RmBB, const BasicBlock *DestBB);
|
||||
bool hasMI() const {
|
||||
return (MachineProfile != 0);
|
||||
}
|
||||
};
|
||||
|
||||
typedef ProfileInfoT<Function, BasicBlock> ProfileInfo;
|
||||
typedef ProfileInfoT<MachineFunction, MachineBasicBlock> MachineProfileInfo;
|
||||
|
||||
/// createProfileLoaderPass - This function returns a Pass that loads the
|
||||
/// profiling information for the module from the specified filename, making
|
||||
/// it available to the optimizers.
|
||||
Pass *createProfileLoaderPass(const std::string &Filename);
|
||||
|
||||
raw_ostream& operator<<(raw_ostream &O, ProfileInfo::Edge E);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -51,6 +51,10 @@ class Argument : public Value, public ilist_node<Argument> {
|
||||
/// in its containing function.
|
||||
bool hasByValAttr() const;
|
||||
|
||||
/// hasNestAttr - Return true if this argument has the nest attribute on
|
||||
/// it in its containing function.
|
||||
bool hasNestAttr() const;
|
||||
|
||||
/// hasNoAliasAttr - Return true if this argument has the noalias attribute on
|
||||
/// it in its containing function.
|
||||
bool hasNoAliasAttr() const;
|
||||
|
@ -25,53 +25,52 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
struct BPNode {
|
||||
BPNode* Next;
|
||||
uintptr_t& PtrRef;
|
||||
|
||||
BPNode(BPNode* n, uintptr_t& pref)
|
||||
: Next(n), PtrRef(pref) {
|
||||
PtrRef = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct BPEntry {
|
||||
union { BPNode* Head; void* Ptr; };
|
||||
BPEntry() : Head(NULL) {}
|
||||
void SetPtr(BPNode*& FreeList, void* P);
|
||||
};
|
||||
|
||||
class BPKey {
|
||||
unsigned Raw;
|
||||
public:
|
||||
BPKey(SerializedPtrID PtrId) : Raw(PtrId << 1) { assert (PtrId > 0); }
|
||||
BPKey(unsigned code, unsigned) : Raw(code) {}
|
||||
|
||||
void MarkFinal() { Raw |= 0x1; }
|
||||
bool hasFinalPtr() const { return Raw & 0x1 ? true : false; }
|
||||
SerializedPtrID getID() const { return Raw >> 1; }
|
||||
|
||||
static inline BPKey getEmptyKey() { return BPKey(0,0); }
|
||||
static inline BPKey getTombstoneKey() { return BPKey(1,0); }
|
||||
static inline unsigned getHashValue(const BPKey& K) { return K.Raw & ~0x1; }
|
||||
|
||||
static bool isEqual(const BPKey& K1, const BPKey& K2) {
|
||||
return (K1.Raw ^ K2.Raw) & ~0x1 ? false : true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct isPodLike<BPKey> { static const bool value = true; };
|
||||
template <>
|
||||
struct isPodLike<BPEntry> { static const bool value = true; };
|
||||
|
||||
class Deserializer {
|
||||
|
||||
//===----------------------------------------------------------===//
|
||||
// Internal type definitions.
|
||||
//===----------------------------------------------------------===//
|
||||
|
||||
struct BPNode {
|
||||
BPNode* Next;
|
||||
uintptr_t& PtrRef;
|
||||
|
||||
BPNode(BPNode* n, uintptr_t& pref)
|
||||
: Next(n), PtrRef(pref) {
|
||||
PtrRef = 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct BPEntry {
|
||||
union { BPNode* Head; void* Ptr; };
|
||||
|
||||
BPEntry() : Head(NULL) {}
|
||||
|
||||
static inline bool isPod() { return true; }
|
||||
|
||||
void SetPtr(BPNode*& FreeList, void* P);
|
||||
};
|
||||
|
||||
class BPKey {
|
||||
unsigned Raw;
|
||||
|
||||
public:
|
||||
BPKey(SerializedPtrID PtrId) : Raw(PtrId << 1) { assert (PtrId > 0); }
|
||||
BPKey(unsigned code, unsigned) : Raw(code) {}
|
||||
|
||||
void MarkFinal() { Raw |= 0x1; }
|
||||
bool hasFinalPtr() const { return Raw & 0x1 ? true : false; }
|
||||
SerializedPtrID getID() const { return Raw >> 1; }
|
||||
|
||||
static inline BPKey getEmptyKey() { return BPKey(0,0); }
|
||||
static inline BPKey getTombstoneKey() { return BPKey(1,0); }
|
||||
static inline unsigned getHashValue(const BPKey& K) { return K.Raw & ~0x1; }
|
||||
|
||||
static bool isEqual(const BPKey& K1, const BPKey& K2) {
|
||||
return (K1.Raw ^ K2.Raw) & ~0x1 ? false : true;
|
||||
}
|
||||
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
|
||||
typedef llvm::DenseMap<BPKey,BPEntry,BPKey,BPEntry> MapTy;
|
||||
|
||||
|
@ -68,7 +68,10 @@ namespace CallingConv {
|
||||
ARM_AAPCS = 67,
|
||||
|
||||
/// ARM_AAPCS_VFP - Same as ARM_AAPCS, but uses hard floating point ABI.
|
||||
ARM_AAPCS_VFP = 68
|
||||
ARM_AAPCS_VFP = 68,
|
||||
|
||||
/// MSP430_INTR - Calling convention used for MSP430 interrupt routines.
|
||||
MSP430_INTR = 69
|
||||
};
|
||||
} // End CallingConv namespace
|
||||
|
||||
|
@ -1,108 +0,0 @@
|
||||
//===--------- BreakCriticalMachineEdge.h - Break critical edges ---------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// Helper function to break a critical machine edge.
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_BREAKCRITICALMACHINEEDGE_H
|
||||
#define LLVM_CODEGEN_BREAKCRITICALMACHINEEDGE_H
|
||||
|
||||
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
MachineBasicBlock* SplitCriticalMachineEdge(MachineBasicBlock* src,
|
||||
MachineBasicBlock* dst) {
|
||||
MachineFunction &MF = *src->getParent();
|
||||
const BasicBlock* srcBB = src->getBasicBlock();
|
||||
|
||||
MachineBasicBlock* crit_mbb = MF.CreateMachineBasicBlock(srcBB);
|
||||
|
||||
// modify the llvm control flow graph
|
||||
src->removeSuccessor(dst);
|
||||
src->addSuccessor(crit_mbb);
|
||||
crit_mbb->addSuccessor(dst);
|
||||
|
||||
// insert the new block into the machine function.
|
||||
MF.push_back(crit_mbb);
|
||||
|
||||
// insert a unconditional branch linking the new block to dst
|
||||
const TargetMachine& TM = MF.getTarget();
|
||||
const TargetInstrInfo* TII = TM.getInstrInfo();
|
||||
std::vector<MachineOperand> emptyConditions;
|
||||
TII->InsertBranch(*crit_mbb, dst, (MachineBasicBlock*)0,
|
||||
emptyConditions);
|
||||
|
||||
// modify every branch in src that points to dst to point to the new
|
||||
// machine basic block instead:
|
||||
MachineBasicBlock::iterator mii = src->end();
|
||||
bool found_branch = false;
|
||||
while (mii != src->begin()) {
|
||||
mii--;
|
||||
// if there are no more branches, finish the loop
|
||||
if (!mii->getDesc().isTerminator()) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Scan the operands of this branch, replacing any uses of dst with
|
||||
// crit_mbb.
|
||||
for (unsigned i = 0, e = mii->getNumOperands(); i != e; ++i) {
|
||||
MachineOperand & mo = mii->getOperand(i);
|
||||
if (mo.isMBB() && mo.getMBB() == dst) {
|
||||
found_branch = true;
|
||||
mo.setMBB(crit_mbb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is tentative. It may be necessary to fix this code. Maybe
|
||||
// I am inserting too many gotos, but I am trusting that the asm printer
|
||||
// will optimize the unnecessary gotos.
|
||||
if(!found_branch) {
|
||||
TII->InsertBranch(*src, crit_mbb, (MachineBasicBlock*)0,
|
||||
emptyConditions);
|
||||
}
|
||||
|
||||
/// Change all the phi functions in dst, so that the incoming block be
|
||||
/// crit_mbb, instead of src
|
||||
for(mii = dst->begin(); mii != dst->end(); mii++) {
|
||||
/// the first instructions are always phi functions.
|
||||
if(mii->getOpcode() != TargetInstrInfo::PHI)
|
||||
break;
|
||||
|
||||
// Find the operands corresponding to the source block
|
||||
std::vector<unsigned> toRemove;
|
||||
unsigned reg = 0;
|
||||
for (unsigned u = 0; u != mii->getNumOperands(); ++u)
|
||||
if (mii->getOperand(u).isMBB() &&
|
||||
mii->getOperand(u).getMBB() == src) {
|
||||
reg = mii->getOperand(u-1).getReg();
|
||||
toRemove.push_back(u-1);
|
||||
}
|
||||
// Remove all uses of this MBB
|
||||
for (std::vector<unsigned>::reverse_iterator I = toRemove.rbegin(),
|
||||
E = toRemove.rend(); I != E; ++I) {
|
||||
mii->RemoveOperand(*I+1);
|
||||
mii->RemoveOperand(*I);
|
||||
}
|
||||
|
||||
// Add a single use corresponding to the new MBB
|
||||
mii->addOperand(MachineOperand::CreateReg(reg, false));
|
||||
mii->addOperand(MachineOperand::CreateMBB(crit_mbb));
|
||||
}
|
||||
|
||||
return crit_mbb;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
39
include/llvm/CodeGen/CalcSpillWeights.h
Normal file
39
include/llvm/CodeGen/CalcSpillWeights.h
Normal file
@ -0,0 +1,39 @@
|
||||
//===---------------- lib/CodeGen/CalcSpillWeights.h ------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef LLVM_CODEGEN_CALCSPILLWEIGHTS_H
|
||||
#define LLVM_CODEGEN_CALCSPILLWEIGHTS_H
|
||||
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class LiveInterval;
|
||||
|
||||
/// CalculateSpillWeights - Compute spill weights for all virtual register
|
||||
/// live intervals.
|
||||
class CalculateSpillWeights : public MachineFunctionPass {
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
CalculateSpillWeights() : MachineFunctionPass(&ID) {}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &au) const;
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &fn);
|
||||
|
||||
private:
|
||||
/// Returns true if the given live interval is zero length.
|
||||
bool isZeroLengthInterval(LiveInterval *li) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LLVM_CODEGEN_CALCSPILLWEIGHTS_H
|
@ -93,7 +93,7 @@ void SelectRoot(SelectionDAG &DAG) {
|
||||
// a reference to the root node, preventing it from being deleted,
|
||||
// and tracking any changes of the root.
|
||||
HandleSDNode Dummy(CurDAG->getRoot());
|
||||
ISelPosition = next(SelectionDAG::allnodes_iterator(CurDAG->getRoot().getNode()));
|
||||
ISelPosition = llvm::next(SelectionDAG::allnodes_iterator(CurDAG->getRoot().getNode()));
|
||||
|
||||
// The AllNodes list is now topological-sorted. Visit the
|
||||
// nodes by starting at the end of the list (the root of the
|
||||
@ -110,8 +110,7 @@ void SelectRoot(SelectionDAG &DAG) {
|
||||
DAG.setSubgraphColor(Node, "red");
|
||||
#endif
|
||||
SDNode *ResNode = Select(SDValue(Node, 0));
|
||||
// If node should not be replaced,
|
||||
// continue with the next one.
|
||||
// If node should not be replaced, continue with the next one.
|
||||
if (ResNode == Node)
|
||||
continue;
|
||||
// Replace node.
|
||||
|
@ -98,14 +98,6 @@ class FastISel {
|
||||
///
|
||||
bool SelectOperator(User *I, unsigned Opcode);
|
||||
|
||||
/// TargetSelectInstruction - This method is called by target-independent
|
||||
/// code when the normal FastISel process fails to select an instruction.
|
||||
/// This gives targets a chance to emit code for anything that doesn't
|
||||
/// fit into FastISel's framework. It returns true if it was successful.
|
||||
///
|
||||
virtual bool
|
||||
TargetSelectInstruction(Instruction *I) = 0;
|
||||
|
||||
/// getRegForValue - Create a virtual register and arrange for it to
|
||||
/// be assigned the value for the given LLVM value.
|
||||
unsigned getRegForValue(Value *V);
|
||||
@ -134,6 +126,14 @@ class FastISel {
|
||||
#endif
|
||||
);
|
||||
|
||||
/// TargetSelectInstruction - This method is called by target-independent
|
||||
/// code when the normal FastISel process fails to select an instruction.
|
||||
/// This gives targets a chance to emit code for anything that doesn't
|
||||
/// fit into FastISel's framework. It returns true if it was successful.
|
||||
///
|
||||
virtual bool
|
||||
TargetSelectInstruction(Instruction *I) = 0;
|
||||
|
||||
/// FastEmit_r - This method is called by target-independent code
|
||||
/// to request that an instruction with the given type and opcode
|
||||
/// be emitted.
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "llvm/CodeGen/SchedulerRegistry.h"
|
||||
#include "llvm/CodeGen/GCs.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace {
|
||||
struct ForceCodegenLinking {
|
||||
|
@ -112,10 +112,13 @@ namespace llvm {
|
||||
return (unsigned)(IntervalPercentage * indexes_->getFunctionSize());
|
||||
}
|
||||
|
||||
/// conflictsWithPhysRegDef - Returns true if the specified register
|
||||
/// is defined during the duration of the specified interval.
|
||||
bool conflictsWithPhysRegDef(const LiveInterval &li, VirtRegMap &vrm,
|
||||
unsigned reg);
|
||||
/// conflictsWithPhysReg - Returns true if the specified register is used or
|
||||
/// defined during the duration of the specified interval. Copies to and
|
||||
/// from li.reg are allowed. This method is only able to analyze simple
|
||||
/// ranges that stay within a single basic block. Anything else is
|
||||
/// considered a conflict.
|
||||
bool conflictsWithPhysReg(const LiveInterval &li, VirtRegMap &vrm,
|
||||
unsigned reg);
|
||||
|
||||
/// conflictsWithPhysRegRef - Similar to conflictsWithPhysRegRef except
|
||||
/// it can check use as well.
|
||||
@ -186,6 +189,10 @@ namespace llvm {
|
||||
return indexes_->getMBBFromIndex(index);
|
||||
}
|
||||
|
||||
SlotIndex getMBBTerminatorGap(const MachineBasicBlock *mbb) {
|
||||
return indexes_->getTerminatorGap(mbb);
|
||||
}
|
||||
|
||||
SlotIndex InsertMachineInstrInMaps(MachineInstr *MI) {
|
||||
return indexes_->insertMachineInstrInMaps(MI);
|
||||
}
|
||||
|
@ -283,6 +283,11 @@ class LiveVariables : public MachineFunctionPass {
|
||||
return getVarInfo(Reg).isLiveIn(MBB, Reg, *MRI);
|
||||
}
|
||||
|
||||
/// isLiveOut - Determine if Reg is live out from MBB, when not considering
|
||||
/// PHI nodes. This means that Reg is either killed by a successor block or
|
||||
/// passed through one.
|
||||
bool isLiveOut(unsigned Reg, const MachineBasicBlock &MBB);
|
||||
|
||||
/// addNewBlock - Add a new basic block BB between DomBB and SuccBB. All
|
||||
/// variables that are live out of DomBB and live into SuccBB will be marked
|
||||
/// as passing live through BB. This method assumes that the machine code is
|
||||
|
@ -327,7 +327,20 @@ class MachineFrameInfo {
|
||||
/// setMaxAlignment - Set the preferred alignment.
|
||||
///
|
||||
void setMaxAlignment(unsigned Align) { MaxAlignment = Align; }
|
||||
|
||||
|
||||
/// calculateMaxStackAlignment() - If there is a local object which requires
|
||||
/// greater alignment than the current max alignment, adjust accordingly.
|
||||
void calculateMaxStackAlignment() {
|
||||
for (int i = getObjectIndexBegin(),
|
||||
e = getObjectIndexEnd(); i != e; ++i) {
|
||||
if (isDeadObjectIndex(i))
|
||||
continue;
|
||||
|
||||
unsigned Align = getObjectAlignment(i);
|
||||
MaxAlignment = std::max(MaxAlignment, Align);
|
||||
}
|
||||
}
|
||||
|
||||
/// hasCalls - Return true if the current function has no function calls.
|
||||
/// This is only valid during or after prolog/epilog code emission.
|
||||
///
|
||||
|
@ -320,6 +320,11 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
/// loads the instruction does are invariant (if it does multiple loads).
|
||||
bool isInvariantLoad(AliasAnalysis *AA) const;
|
||||
|
||||
/// isConstantValuePHI - If the specified instruction is a PHI that always
|
||||
/// merges together the same virtual register, return the register, otherwise
|
||||
/// return 0.
|
||||
unsigned isConstantValuePHI() const;
|
||||
|
||||
//
|
||||
// Debugging support
|
||||
//
|
||||
|
115
include/llvm/CodeGen/MachineSSAUpdater.h
Normal file
115
include/llvm/CodeGen/MachineSSAUpdater.h
Normal file
@ -0,0 +1,115 @@
|
||||
//===-- MachineSSAUpdater.h - Unstructured SSA Update Tool ------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares the MachineSSAUpdater class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_MACHINESSAUPDATER_H
|
||||
#define LLVM_CODEGEN_MACHINESSAUPDATER_H
|
||||
|
||||
namespace llvm {
|
||||
class MachineBasicBlock;
|
||||
class MachineFunction;
|
||||
class MachineInstr;
|
||||
class MachineOperand;
|
||||
class MachineRegisterInfo;
|
||||
class TargetInstrInfo;
|
||||
class TargetRegisterClass;
|
||||
template<typename T> class SmallVectorImpl;
|
||||
|
||||
/// MachineSSAUpdater - This class updates SSA form for a set of virtual
|
||||
/// registers defined in multiple blocks. This is used when code duplication
|
||||
/// or another unstructured transformation wants to rewrite a set of uses of one
|
||||
/// vreg with uses of a set of vregs.
|
||||
class MachineSSAUpdater {
|
||||
/// AvailableVals - This keeps track of which value to use on a per-block
|
||||
/// basis. When we insert PHI nodes, we keep track of them here.
|
||||
//typedef DenseMap<MachineBasicBlock*, unsigned > AvailableValsTy;
|
||||
void *AV;
|
||||
|
||||
/// IncomingPredInfo - We use this as scratch space when doing our recursive
|
||||
/// walk. This should only be used in GetValueInBlockInternal, normally it
|
||||
/// should be empty.
|
||||
//std::vector<std::pair<MachineBasicBlock*, unsigned > > IncomingPredInfo;
|
||||
void *IPI;
|
||||
|
||||
/// VR - Current virtual register whose uses are being updated.
|
||||
unsigned VR;
|
||||
|
||||
/// VRC - Register class of the current virtual register.
|
||||
const TargetRegisterClass *VRC;
|
||||
|
||||
/// InsertedPHIs - If this is non-null, the MachineSSAUpdater adds all PHI
|
||||
/// nodes that it creates to the vector.
|
||||
SmallVectorImpl<MachineInstr*> *InsertedPHIs;
|
||||
|
||||
const TargetInstrInfo *TII;
|
||||
MachineRegisterInfo *MRI;
|
||||
public:
|
||||
/// MachineSSAUpdater constructor. If InsertedPHIs is specified, it will be
|
||||
/// filled in with all PHI Nodes created by rewriting.
|
||||
explicit MachineSSAUpdater(MachineFunction &MF,
|
||||
SmallVectorImpl<MachineInstr*> *InsertedPHIs = 0);
|
||||
~MachineSSAUpdater();
|
||||
|
||||
/// Initialize - Reset this object to get ready for a new set of SSA
|
||||
/// updates.
|
||||
void Initialize(unsigned V);
|
||||
|
||||
/// AddAvailableValue - Indicate that a rewritten value is available at the
|
||||
/// end of the specified block with the specified value.
|
||||
void AddAvailableValue(MachineBasicBlock *BB, unsigned V);
|
||||
|
||||
/// HasValueForBlock - Return true if the MachineSSAUpdater already has a
|
||||
/// value for the specified block.
|
||||
bool HasValueForBlock(MachineBasicBlock *BB) const;
|
||||
|
||||
/// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is
|
||||
/// live at the end of the specified block.
|
||||
unsigned GetValueAtEndOfBlock(MachineBasicBlock *BB);
|
||||
|
||||
/// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that
|
||||
/// is live in the middle of the specified block.
|
||||
///
|
||||
/// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one
|
||||
/// important case: if there is a definition of the rewritten value after the
|
||||
/// 'use' in BB. Consider code like this:
|
||||
///
|
||||
/// X1 = ...
|
||||
/// SomeBB:
|
||||
/// use(X)
|
||||
/// X2 = ...
|
||||
/// br Cond, SomeBB, OutBB
|
||||
///
|
||||
/// In this case, there are two values (X1 and X2) added to the AvailableVals
|
||||
/// set by the client of the rewriter, and those values are both live out of
|
||||
/// their respective blocks. However, the use of X happens in the *middle* of
|
||||
/// a block. Because of this, we need to insert a new PHI node in SomeBB to
|
||||
/// merge the appropriate values, and this value isn't live out of the block.
|
||||
///
|
||||
unsigned GetValueInMiddleOfBlock(MachineBasicBlock *BB);
|
||||
|
||||
/// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes,
|
||||
/// which use their value in the corresponding predecessor. Note that this
|
||||
/// will not work if the use is supposed to be rewritten to a value defined in
|
||||
/// the same block as the use, but above it. Any 'AddAvailableValue's added
|
||||
/// for the use's block will be considered to be below it.
|
||||
void RewriteUse(MachineOperand &U);
|
||||
|
||||
private:
|
||||
void ReplaceRegWith(unsigned OldReg, unsigned NewReg);
|
||||
unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB);
|
||||
void operator=(const MachineSSAUpdater&); // DO NOT IMPLEMENT
|
||||
MachineSSAUpdater(const MachineSSAUpdater&); // DO NOT IMPLEMENT
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -131,7 +131,7 @@ namespace llvm {
|
||||
|
||||
/// TailDuplicate Pass - Duplicate blocks with unconditional branches
|
||||
/// into tails of their predecessors.
|
||||
FunctionPass *createTailDuplicatePass();
|
||||
FunctionPass *createTailDuplicatePass(bool PreRegAlloc = false);
|
||||
|
||||
/// IfConverter Pass - This pass performs machine code if conversion.
|
||||
FunctionPass *createIfConverterPass();
|
||||
@ -191,6 +191,10 @@ namespace llvm {
|
||||
/// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow.
|
||||
FunctionPass *createSjLjEHPass(const TargetLowering *tli);
|
||||
|
||||
/// createMaxStackAlignmentCalculatorPass() - Determine the maximum required
|
||||
/// alignment for a function.
|
||||
FunctionPass* createMaxStackAlignmentCalculatorPass();
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -110,6 +110,46 @@ class SelectionDAG {
|
||||
/// SelectionDAG.
|
||||
BumpPtrAllocator Allocator;
|
||||
|
||||
/// NodeOrdering - Assigns a "line number" value to each SDNode that
|
||||
/// corresponds to the "line number" of the original LLVM instruction. This
|
||||
/// used for turning off scheduling, because we'll forgo the normal scheduling
|
||||
/// algorithm and output the instructions according to this ordering.
|
||||
class NodeOrdering {
|
||||
/// LineNo - The line of the instruction the node corresponds to. A value of
|
||||
/// `0' means it's not assigned.
|
||||
unsigned LineNo;
|
||||
std::map<const SDNode*, unsigned> Order;
|
||||
|
||||
void operator=(const NodeOrdering&); // Do not implement.
|
||||
NodeOrdering(const NodeOrdering&); // Do not implement.
|
||||
public:
|
||||
NodeOrdering() : LineNo(0) {}
|
||||
|
||||
void add(const SDNode *Node) {
|
||||
assert(LineNo && "Invalid line number!");
|
||||
Order[Node] = LineNo;
|
||||
}
|
||||
void remove(const SDNode *Node) {
|
||||
std::map<const SDNode*, unsigned>::iterator Itr = Order.find(Node);
|
||||
if (Itr != Order.end())
|
||||
Order.erase(Itr);
|
||||
}
|
||||
void clear() {
|
||||
Order.clear();
|
||||
LineNo = 1;
|
||||
}
|
||||
unsigned getLineNo(const SDNode *Node) {
|
||||
unsigned LN = Order[Node];
|
||||
assert(LN && "Node isn't in ordering map!");
|
||||
return LN;
|
||||
}
|
||||
void newInst() {
|
||||
++LineNo;
|
||||
}
|
||||
|
||||
void dump() const;
|
||||
} *Ordering;
|
||||
|
||||
/// VerifyNode - Sanity check the given node. Aborts if it is invalid.
|
||||
void VerifyNode(SDNode *N);
|
||||
|
||||
@ -120,6 +160,9 @@ class SelectionDAG {
|
||||
DenseSet<SDNode *> &visited,
|
||||
int level, bool &printed);
|
||||
|
||||
void operator=(const SelectionDAG&); // Do not implement.
|
||||
SelectionDAG(const SelectionDAG&); // Do not implement.
|
||||
|
||||
public:
|
||||
SelectionDAG(TargetLowering &tli, FunctionLoweringInfo &fli);
|
||||
~SelectionDAG();
|
||||
@ -199,6 +242,13 @@ class SelectionDAG {
|
||||
return Root = N;
|
||||
}
|
||||
|
||||
/// NewInst - Tell the ordering object that we're processing a new
|
||||
/// instruction.
|
||||
void NewInst() {
|
||||
if (Ordering)
|
||||
Ordering->newInst();
|
||||
}
|
||||
|
||||
/// Combine - This iterates over the nodes in the SelectionDAG, folding
|
||||
/// certain types of nodes together, or eliminating superfluous nodes. The
|
||||
/// Level argument controls whether Combine is allowed to produce nodes and
|
||||
@ -220,7 +270,7 @@ class SelectionDAG {
|
||||
///
|
||||
/// Note that this is an involved process that may invalidate pointers into
|
||||
/// the graph.
|
||||
void Legalize(bool TypesNeedLegalizing, CodeGenOpt::Level OptLevel);
|
||||
void Legalize(CodeGenOpt::Level OptLevel);
|
||||
|
||||
/// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG
|
||||
/// that only uses vector math operations supported by the target. This is
|
||||
@ -890,6 +940,16 @@ class SelectionDAG {
|
||||
/// vector op and fill the end of the resulting vector with UNDEFS.
|
||||
SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0);
|
||||
|
||||
/// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a
|
||||
/// location that is 'Dist' units away from the location that the 'Base' load
|
||||
/// is loading from.
|
||||
bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base,
|
||||
unsigned Bytes, int Dist) const;
|
||||
|
||||
/// InferPtrAlignment - Infer alignment of a load / store address. Return 0 if
|
||||
/// it cannot be inferred.
|
||||
unsigned InferPtrAlignment(SDValue Ptr) const;
|
||||
|
||||
private:
|
||||
bool RemoveNodeFromCSEMaps(SDNode *N);
|
||||
void AddModifiedNodeToCSEMaps(SDNode *N, DAGUpdateListener *UpdateListener);
|
||||
|
@ -113,7 +113,6 @@ class SelectionDAGISel : public MachineFunctionPass {
|
||||
// Calls to these functions are generated by tblgen.
|
||||
SDNode *Select_INLINEASM(SDValue N);
|
||||
SDNode *Select_UNDEF(const SDValue &N);
|
||||
SDNode *Select_DBG_LABEL(const SDValue &N);
|
||||
SDNode *Select_EH_LABEL(const SDValue &N);
|
||||
void CannotYetSelect(SDValue N);
|
||||
void CannotYetSelectIntrinsic(SDValue N);
|
||||
|
@ -891,8 +891,9 @@ template<> struct DenseMapInfo<SDValue> {
|
||||
static bool isEqual(const SDValue &LHS, const SDValue &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
template <> struct isPodLike<SDValue> { static const bool value = true; };
|
||||
|
||||
|
||||
/// simplify_type specializations - Allow casting operators to work directly on
|
||||
/// SDValues as if they were SDNode*'s.
|
||||
@ -1095,7 +1096,7 @@ class SDNode : public FoldingSetNode, public ilist_node<SDNode> {
|
||||
/// hasOneUse - Return true if there is exactly one use of this node.
|
||||
///
|
||||
bool hasOneUse() const {
|
||||
return !use_empty() && next(use_begin()) == use_end();
|
||||
return !use_empty() && llvm::next(use_begin()) == use_end();
|
||||
}
|
||||
|
||||
/// use_size - Return the number of uses of this node. This method takes
|
||||
@ -2397,6 +2398,11 @@ class SDNodeIterator : public std::iterator<std::forward_iterator_tag,
|
||||
SDNodeIterator operator++(int) { // Postincrement
|
||||
SDNodeIterator tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
size_t operator-(SDNodeIterator Other) const {
|
||||
assert(Node == Other.Node &&
|
||||
"Cannot compare iterators of two different nodes!");
|
||||
return Operand - Other.Operand;
|
||||
}
|
||||
|
||||
static SDNodeIterator begin(SDNode *N) { return SDNodeIterator(N, 0); }
|
||||
static SDNodeIterator end (SDNode *N) {
|
||||
|
@ -343,8 +343,10 @@ namespace llvm {
|
||||
static inline bool isEqual(const SlotIndex &LHS, const SlotIndex &RHS) {
|
||||
return (LHS == RHS);
|
||||
}
|
||||
static inline bool isPod() { return false; }
|
||||
};
|
||||
|
||||
template <> struct isPodLike<SlotIndex> { static const bool value = true; };
|
||||
|
||||
|
||||
inline raw_ostream& operator<<(raw_ostream &os, SlotIndex li) {
|
||||
li.print(os);
|
||||
|
@ -47,35 +47,36 @@ namespace llvm {
|
||||
f80 = 9, // This is a 80 bit floating point value
|
||||
f128 = 10, // This is a 128 bit floating point value
|
||||
ppcf128 = 11, // This is a PPC 128-bit floating point value
|
||||
Flag = 12, // This is a condition code or machine flag.
|
||||
|
||||
isVoid = 13, // This has no value
|
||||
v2i8 = 12, // 2 x i8
|
||||
v4i8 = 13, // 4 x i8
|
||||
v8i8 = 14, // 8 x i8
|
||||
v16i8 = 15, // 16 x i8
|
||||
v32i8 = 16, // 32 x i8
|
||||
v2i16 = 17, // 2 x i16
|
||||
v4i16 = 18, // 4 x i16
|
||||
v8i16 = 19, // 8 x i16
|
||||
v16i16 = 20, // 16 x i16
|
||||
v2i32 = 21, // 2 x i32
|
||||
v4i32 = 22, // 4 x i32
|
||||
v8i32 = 23, // 8 x i32
|
||||
v1i64 = 24, // 1 x i64
|
||||
v2i64 = 25, // 2 x i64
|
||||
v4i64 = 26, // 4 x i64
|
||||
|
||||
v2i8 = 14, // 2 x i8
|
||||
v4i8 = 15, // 4 x i8
|
||||
v8i8 = 16, // 8 x i8
|
||||
v16i8 = 17, // 16 x i8
|
||||
v32i8 = 18, // 32 x i8
|
||||
v2i16 = 19, // 2 x i16
|
||||
v4i16 = 20, // 4 x i16
|
||||
v8i16 = 21, // 8 x i16
|
||||
v16i16 = 22, // 16 x i16
|
||||
v2i32 = 23, // 2 x i32
|
||||
v4i32 = 24, // 4 x i32
|
||||
v8i32 = 25, // 8 x i32
|
||||
v1i64 = 26, // 1 x i64
|
||||
v2i64 = 27, // 2 x i64
|
||||
v4i64 = 28, // 4 x i64
|
||||
|
||||
v2f32 = 29, // 2 x f32
|
||||
v4f32 = 30, // 4 x f32
|
||||
v8f32 = 31, // 8 x f32
|
||||
v2f64 = 32, // 2 x f64
|
||||
v4f64 = 33, // 4 x f64
|
||||
v2f32 = 27, // 2 x f32
|
||||
v4f32 = 28, // 4 x f32
|
||||
v8f32 = 29, // 8 x f32
|
||||
v2f64 = 30, // 2 x f64
|
||||
v4f64 = 31, // 4 x f64
|
||||
|
||||
FIRST_VECTOR_VALUETYPE = v2i8,
|
||||
LAST_VECTOR_VALUETYPE = v4f64,
|
||||
|
||||
Flag = 32, // This glues nodes together during pre-RA sched
|
||||
|
||||
isVoid = 33, // This has no value
|
||||
|
||||
LAST_VALUETYPE = 34, // This always remains at the end of the list.
|
||||
|
||||
// This is the current maximum for LAST_VALUETYPE.
|
||||
@ -166,6 +167,12 @@ namespace llvm {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
/// getScalarType - If this is a vector type, return the element type,
|
||||
/// otherwise return this.
|
||||
MVT getScalarType() const {
|
||||
return isVector() ? getVectorElementType() : *this;
|
||||
}
|
||||
|
||||
MVT getVectorElementType() const {
|
||||
switch (SimpleTy) {
|
||||
@ -524,6 +531,12 @@ namespace llvm {
|
||||
return V;
|
||||
}
|
||||
|
||||
/// getScalarType - If this is a vector type, return the element type,
|
||||
/// otherwise return this.
|
||||
EVT getScalarType() const {
|
||||
return isVector() ? getVectorElementType() : *this;
|
||||
}
|
||||
|
||||
/// getVectorElementType - Given a vector type, return the type of
|
||||
/// each element.
|
||||
EVT getVectorElementType() const {
|
||||
|
@ -31,30 +31,31 @@ def f64 : ValueType<64 , 8>; // 64-bit floating point value
|
||||
def f80 : ValueType<80 , 9>; // 80-bit floating point value
|
||||
def f128 : ValueType<128, 10>; // 128-bit floating point value
|
||||
def ppcf128: ValueType<128, 11>; // PPC 128-bit floating point value
|
||||
def FlagVT : ValueType<0 , 12>; // Condition code or machine flag
|
||||
def isVoid : ValueType<0 , 13>; // Produces no value
|
||||
|
||||
def v2i8 : ValueType<16 , 14>; // 2 x i8 vector value
|
||||
def v4i8 : ValueType<32 , 15>; // 4 x i8 vector value
|
||||
def v8i8 : ValueType<64 , 16>; // 8 x i8 vector value
|
||||
def v16i8 : ValueType<128, 17>; // 16 x i8 vector value
|
||||
def v32i8 : ValueType<256, 18>; // 32 x i8 vector value
|
||||
def v2i16 : ValueType<32 , 19>; // 2 x i16 vector value
|
||||
def v4i16 : ValueType<64 , 20>; // 4 x i16 vector value
|
||||
def v8i16 : ValueType<128, 21>; // 8 x i16 vector value
|
||||
def v16i16 : ValueType<256, 22>; // 16 x i16 vector value
|
||||
def v2i32 : ValueType<64 , 23>; // 2 x i32 vector value
|
||||
def v4i32 : ValueType<128, 24>; // 4 x i32 vector value
|
||||
def v8i32 : ValueType<256, 25>; // 8 x i32 vector value
|
||||
def v1i64 : ValueType<64 , 26>; // 1 x i64 vector value
|
||||
def v2i64 : ValueType<128, 27>; // 2 x i64 vector value
|
||||
def v4i64 : ValueType<256, 28>; // 4 x f64 vector value
|
||||
def v2i8 : ValueType<16 , 12>; // 2 x i8 vector value
|
||||
def v4i8 : ValueType<32 , 13>; // 4 x i8 vector value
|
||||
def v8i8 : ValueType<64 , 14>; // 8 x i8 vector value
|
||||
def v16i8 : ValueType<128, 15>; // 16 x i8 vector value
|
||||
def v32i8 : ValueType<256, 16>; // 32 x i8 vector value
|
||||
def v2i16 : ValueType<32 , 17>; // 2 x i16 vector value
|
||||
def v4i16 : ValueType<64 , 18>; // 4 x i16 vector value
|
||||
def v8i16 : ValueType<128, 19>; // 8 x i16 vector value
|
||||
def v16i16 : ValueType<256, 20>; // 16 x i16 vector value
|
||||
def v2i32 : ValueType<64 , 21>; // 2 x i32 vector value
|
||||
def v4i32 : ValueType<128, 22>; // 4 x i32 vector value
|
||||
def v8i32 : ValueType<256, 23>; // 8 x i32 vector value
|
||||
def v1i64 : ValueType<64 , 24>; // 1 x i64 vector value
|
||||
def v2i64 : ValueType<128, 25>; // 2 x i64 vector value
|
||||
def v4i64 : ValueType<256, 26>; // 4 x f64 vector value
|
||||
|
||||
def v2f32 : ValueType<64, 29>; // 2 x f32 vector value
|
||||
def v4f32 : ValueType<128, 30>; // 4 x f32 vector value
|
||||
def v8f32 : ValueType<256, 31>; // 8 x f32 vector value
|
||||
def v2f64 : ValueType<128, 32>; // 2 x f64 vector value
|
||||
def v4f64 : ValueType<256, 33>; // 4 x f64 vector value
|
||||
def v2f32 : ValueType<64, 27>; // 2 x f32 vector value
|
||||
def v4f32 : ValueType<128, 28>; // 4 x f32 vector value
|
||||
def v8f32 : ValueType<256, 29>; // 8 x f32 vector value
|
||||
def v2f64 : ValueType<128, 30>; // 2 x f64 vector value
|
||||
def v4f64 : ValueType<256, 31>; // 4 x f64 vector value
|
||||
|
||||
def FlagVT : ValueType<0 , 32>; // Pre-RA sched glue
|
||||
def isVoid : ValueType<0 , 33>; // Produces no value
|
||||
|
||||
def MetadataVT: ValueType<0, 250>; // Metadata
|
||||
|
||||
|
@ -42,9 +42,10 @@ def hidden;
|
||||
def init;
|
||||
def multi_val;
|
||||
def one_or_more;
|
||||
def optional;
|
||||
def really_hidden;
|
||||
def required;
|
||||
def zero_or_one;
|
||||
def comma_separated;
|
||||
|
||||
// The 'case' construct.
|
||||
def case;
|
||||
@ -77,6 +78,8 @@ def any_empty;
|
||||
def append_cmd;
|
||||
def forward;
|
||||
def forward_as;
|
||||
def forward_value;
|
||||
def forward_transformed_value;
|
||||
def stop_compilation;
|
||||
def unpack_values;
|
||||
def warning;
|
||||
|
@ -70,6 +70,7 @@ namespace llvm {
|
||||
case Intrinsic::dbg_region_start:
|
||||
case Intrinsic::dbg_region_end:
|
||||
case Intrinsic::dbg_declare:
|
||||
case Intrinsic::dbg_value:
|
||||
return true;
|
||||
default: return false;
|
||||
}
|
||||
@ -171,6 +172,25 @@ namespace llvm {
|
||||
}
|
||||
};
|
||||
|
||||
/// DbgValueInst - This represents the llvm.dbg.value instruction.
|
||||
///
|
||||
struct DbgValueInst : public DbgInfoIntrinsic {
|
||||
Value *getValue() const {
|
||||
return cast<MDNode>(getOperand(1))->getElement(0);
|
||||
}
|
||||
Value *getOffset() const { return getOperand(2); }
|
||||
MDNode *getVariable() const { return cast<MDNode>(getOperand(3)); }
|
||||
|
||||
// Methods for support type inquiry through isa, cast, and dyn_cast:
|
||||
static inline bool classof(const DbgValueInst *) { return true; }
|
||||
static inline bool classof(const IntrinsicInst *I) {
|
||||
return I->getIntrinsicID() == Intrinsic::dbg_value;
|
||||
}
|
||||
static inline bool classof(const Value *V) {
|
||||
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
|
||||
}
|
||||
};
|
||||
|
||||
/// MemIntrinsic - This is the common base class for memset/memcpy/memmove.
|
||||
///
|
||||
struct MemIntrinsic : public IntrinsicInst {
|
||||
|
@ -290,6 +290,9 @@ let Properties = [IntrNoMem] in {
|
||||
def int_dbg_func_start : Intrinsic<[llvm_void_ty], [llvm_metadata_ty]>;
|
||||
def int_dbg_declare : Intrinsic<[llvm_void_ty],
|
||||
[llvm_descriptor_ty, llvm_metadata_ty]>;
|
||||
def int_dbg_value : Intrinsic<[llvm_void_ty],
|
||||
[llvm_metadata_ty, llvm_i64_ty,
|
||||
llvm_metadata_ty]>;
|
||||
}
|
||||
|
||||
//===------------------ Exception Handling Intrinsics----------------------===//
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "llvm/Support/Mangler.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/SlowOperationInformer.h"
|
||||
#include <cstdlib>
|
||||
|
||||
namespace {
|
||||
struct ForceVMCoreLinking {
|
||||
|
@ -111,12 +111,10 @@ class Pass {
|
||||
virtual void assignPassManager(PMStack &,
|
||||
PassManagerType = PMT_Unknown) {}
|
||||
/// Check if available pass managers are suitable for this pass or not.
|
||||
virtual void preparePassManager(PMStack &) {}
|
||||
virtual void preparePassManager(PMStack &);
|
||||
|
||||
/// Return what kind of Pass Manager can manage this pass.
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_Unknown;
|
||||
}
|
||||
virtual PassManagerType getPotentialPassManagerType() const;
|
||||
|
||||
// Access AnalysisResolver
|
||||
inline void setResolver(AnalysisResolver *AR) {
|
||||
@ -132,9 +130,7 @@ class Pass {
|
||||
/// particular analysis result to this function, it can then use the
|
||||
/// getAnalysis<AnalysisType>() function, below.
|
||||
///
|
||||
virtual void getAnalysisUsage(AnalysisUsage &) const {
|
||||
// By default, no analysis results are used, all are invalidated.
|
||||
}
|
||||
virtual void getAnalysisUsage(AnalysisUsage &) const;
|
||||
|
||||
/// releaseMemory() - This member can be implemented by a pass if it wants to
|
||||
/// be able to release its memory when it is no longer needed. The default
|
||||
@ -147,11 +143,11 @@ class Pass {
|
||||
/// Optionally implement this function to release pass memory when it is no
|
||||
/// longer used.
|
||||
///
|
||||
virtual void releaseMemory() {}
|
||||
virtual void releaseMemory();
|
||||
|
||||
/// verifyAnalysis() - This member can be implemented by a analysis pass to
|
||||
/// check state of analysis information.
|
||||
virtual void verifyAnalysis() const {}
|
||||
virtual void verifyAnalysis() const;
|
||||
|
||||
// dumpPassStructure - Implement the -debug-passes=PassStructure option
|
||||
virtual void dumpPassStructure(unsigned Offset = 0);
|
||||
@ -221,9 +217,7 @@ class ModulePass : public Pass {
|
||||
PassManagerType T = PMT_ModulePassManager);
|
||||
|
||||
/// Return what kind of Pass Manager can manage this pass.
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_ModulePassManager;
|
||||
}
|
||||
virtual PassManagerType getPotentialPassManagerType() const;
|
||||
|
||||
explicit ModulePass(intptr_t pid) : Pass(pid) {}
|
||||
explicit ModulePass(const void *pid) : Pass(pid) {}
|
||||
@ -245,7 +239,7 @@ class ImmutablePass : public ModulePass {
|
||||
/// and if it does, the overloaded version of initializePass may get access to
|
||||
/// these passes with getAnalysis<>.
|
||||
///
|
||||
virtual void initializePass() {}
|
||||
virtual void initializePass();
|
||||
|
||||
/// ImmutablePasses are never run.
|
||||
///
|
||||
@ -276,7 +270,7 @@ class FunctionPass : public Pass {
|
||||
/// doInitialization - Virtual method overridden by subclasses to do
|
||||
/// any necessary per-module initialization.
|
||||
///
|
||||
virtual bool doInitialization(Module &) { return false; }
|
||||
virtual bool doInitialization(Module &);
|
||||
|
||||
/// runOnFunction - Virtual method overriden by subclasses to do the
|
||||
/// per-function processing of the pass.
|
||||
@ -286,7 +280,7 @@ class FunctionPass : public Pass {
|
||||
/// doFinalization - Virtual method overriden by subclasses to do any post
|
||||
/// processing needed after all passes have run.
|
||||
///
|
||||
virtual bool doFinalization(Module &) { return false; }
|
||||
virtual bool doFinalization(Module &);
|
||||
|
||||
/// runOnModule - On a module, we run this pass by initializing,
|
||||
/// ronOnFunction'ing once for every function in the module, then by
|
||||
@ -303,9 +297,7 @@ class FunctionPass : public Pass {
|
||||
PassManagerType T = PMT_FunctionPassManager);
|
||||
|
||||
/// Return what kind of Pass Manager can manage this pass.
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_FunctionPassManager;
|
||||
}
|
||||
virtual PassManagerType getPotentialPassManagerType() const;
|
||||
};
|
||||
|
||||
|
||||
@ -328,12 +320,12 @@ class BasicBlockPass : public Pass {
|
||||
/// doInitialization - Virtual method overridden by subclasses to do
|
||||
/// any necessary per-module initialization.
|
||||
///
|
||||
virtual bool doInitialization(Module &) { return false; }
|
||||
virtual bool doInitialization(Module &);
|
||||
|
||||
/// doInitialization - Virtual method overridden by BasicBlockPass subclasses
|
||||
/// to do any necessary per-function initialization.
|
||||
///
|
||||
virtual bool doInitialization(Function &) { return false; }
|
||||
virtual bool doInitialization(Function &);
|
||||
|
||||
/// runOnBasicBlock - Virtual method overriden by subclasses to do the
|
||||
/// per-basicblock processing of the pass.
|
||||
@ -343,12 +335,12 @@ class BasicBlockPass : public Pass {
|
||||
/// doFinalization - Virtual method overriden by BasicBlockPass subclasses to
|
||||
/// do any post processing needed after all passes have run.
|
||||
///
|
||||
virtual bool doFinalization(Function &) { return false; }
|
||||
virtual bool doFinalization(Function &);
|
||||
|
||||
/// doFinalization - Virtual method overriden by subclasses to do any post
|
||||
/// processing needed after all passes have run.
|
||||
///
|
||||
virtual bool doFinalization(Module &) { return false; }
|
||||
virtual bool doFinalization(Module &);
|
||||
|
||||
|
||||
// To run this pass on a function, we simply call runOnBasicBlock once for
|
||||
@ -360,9 +352,7 @@ class BasicBlockPass : public Pass {
|
||||
PassManagerType T = PMT_BasicBlockPassManager);
|
||||
|
||||
/// Return what kind of Pass Manager can manage this pass.
|
||||
virtual PassManagerType getPotentialPassManagerType() const {
|
||||
return PMT_BasicBlockPassManager;
|
||||
}
|
||||
virtual PassManagerType getPotentialPassManagerType() const;
|
||||
};
|
||||
|
||||
/// If the user specifies the -time-passes argument on an LLVM tool command line
|
||||
|
@ -986,7 +986,7 @@ template<class DataType>
|
||||
class list_storage<DataType, bool> : public std::vector<DataType> {
|
||||
public:
|
||||
template<class T>
|
||||
void addValue(const T &V) { push_back(V); }
|
||||
void addValue(const T &V) { std::vector<DataType>::push_back(V); }
|
||||
};
|
||||
|
||||
|
||||
@ -1011,7 +1011,7 @@ class list : public Option, public list_storage<DataType, Storage> {
|
||||
typename ParserClass::parser_data_type();
|
||||
if (Parser.parse(*this, ArgName, Arg, Val))
|
||||
return true; // Parse Error!
|
||||
addValue(Val);
|
||||
list_storage<DataType, Storage>::addValue(Val);
|
||||
setPosition(pos);
|
||||
Positions.push_back(pos);
|
||||
return false;
|
||||
|
@ -70,6 +70,16 @@
|
||||
#define DISABLE_INLINE
|
||||
#endif
|
||||
|
||||
// ALWAYS_INLINE - On compilers where we have a directive to do so, mark a
|
||||
// method "always inline" because it is performance sensitive.
|
||||
#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
|
||||
#define ALWAYS_INLINE __attribute__((always_inline))
|
||||
#else
|
||||
// TODO: No idea how to do this with MSVC.
|
||||
#define ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define NORETURN __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER)
|
||||
|
@ -63,7 +63,8 @@ void SetCurrentDebugType(const char *Type);
|
||||
/// This will emit the debug information if -debug is present, and -debug-only
|
||||
/// is not specified, or is specified as "bitset".
|
||||
#define DEBUG_WITH_TYPE(TYPE, X) \
|
||||
do { if (DebugFlag && isCurrentDebugType(TYPE)) { X; } } while (0)
|
||||
do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType(TYPE)) { X; } \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define isCurrentDebugType(X) (false)
|
||||
|
@ -66,7 +66,7 @@ namespace llvm {
|
||||
};
|
||||
|
||||
// Specialize DenseMapInfo for DebugLocTuple.
|
||||
template<> struct DenseMapInfo<DebugLocTuple> {
|
||||
template<> struct DenseMapInfo<DebugLocTuple> {
|
||||
static inline DebugLocTuple getEmptyKey() {
|
||||
return DebugLocTuple(0, 0, ~0U, ~0U);
|
||||
}
|
||||
@ -85,9 +85,9 @@ namespace llvm {
|
||||
LHS.Line == RHS.Line &&
|
||||
LHS.Col == RHS.Col;
|
||||
}
|
||||
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
template <> struct isPodLike<DebugLocTuple> {static const bool value = true;};
|
||||
|
||||
|
||||
/// DebugLocTracker - This class tracks debug location information.
|
||||
///
|
||||
|
@ -79,9 +79,10 @@ namespace llvm {
|
||||
/// Use this instead of assert(0), so that the compiler knows this path
|
||||
/// is not reachable even for NDEBUG builds.
|
||||
#ifndef NDEBUG
|
||||
#define llvm_unreachable(msg) llvm_unreachable_internal(msg, __FILE__, __LINE__)
|
||||
#define llvm_unreachable(msg) \
|
||||
::llvm::llvm_unreachable_internal(msg, __FILE__, __LINE__)
|
||||
#else
|
||||
#define llvm_unreachable(msg) llvm_unreachable_internal()
|
||||
#define llvm_unreachable(msg) ::llvm::llvm_unreachable_internal()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -84,7 +84,7 @@ namespace llvm {
|
||||
|
||||
inline gep_type_iterator gep_type_begin(const User *GEP) {
|
||||
return gep_type_iterator::begin(GEP->getOperand(0)->getType(),
|
||||
GEP->op_begin()+1);
|
||||
GEP->op_begin()+1);
|
||||
}
|
||||
inline gep_type_iterator gep_type_end(const User *GEP) {
|
||||
return gep_type_iterator::end(GEP->op_end());
|
||||
|
@ -269,6 +269,27 @@ class IRBuilder : public Inserter {
|
||||
return Insert(IndirectBrInst::Create(Addr, NumDests));
|
||||
}
|
||||
|
||||
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
|
||||
BasicBlock *UnwindDest, const Twine &Name = "") {
|
||||
Value *Args[] = { 0 };
|
||||
return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args,
|
||||
Args), Name);
|
||||
}
|
||||
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
|
||||
BasicBlock *UnwindDest, Value *Arg1,
|
||||
const Twine &Name = "") {
|
||||
Value *Args[] = { Arg1 };
|
||||
return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args,
|
||||
Args+1), Name);
|
||||
}
|
||||
InvokeInst *CreateInvoke3(Value *Callee, BasicBlock *NormalDest,
|
||||
BasicBlock *UnwindDest, Value *Arg1,
|
||||
Value *Arg2, Value *Arg3,
|
||||
const Twine &Name = "") {
|
||||
Value *Args[] = { Arg1, Arg2, Arg3 };
|
||||
return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args,
|
||||
Args+3), Name);
|
||||
}
|
||||
/// CreateInvoke - Create an invoke instruction.
|
||||
template<typename InputIterator>
|
||||
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
|
||||
@ -386,18 +407,39 @@ class IRBuilder : public Inserter {
|
||||
return Folder.CreateShl(LC, RC);
|
||||
return Insert(BinaryOperator::CreateShl(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
return Folder.CreateShl(LC, RHSC);
|
||||
return Insert(BinaryOperator::CreateShl(LHS, RHSC), Name);
|
||||
}
|
||||
|
||||
Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Folder.CreateLShr(LC, RC);
|
||||
return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
return Folder.CreateLShr(LC, RHSC);
|
||||
return Insert(BinaryOperator::CreateLShr(LHS, RHSC), Name);
|
||||
}
|
||||
|
||||
Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Folder.CreateAShr(LC, RC);
|
||||
return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "") {
|
||||
Constant *RHSC = ConstantInt::get(LHS->getType(), RHS);
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
return Folder.CreateSShr(LC, RHSC);
|
||||
return Insert(BinaryOperator::CreateAShr(LHS, RHSC), Name);
|
||||
}
|
||||
|
||||
Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") {
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS)) {
|
||||
if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isAllOnesValue())
|
||||
|
@ -254,14 +254,17 @@ struct DenseMapInfo<AssertingVH<T> > {
|
||||
static bool isEqual(const AssertingVH<T> &LHS, const AssertingVH<T> &RHS) {
|
||||
return LHS == RHS;
|
||||
}
|
||||
static bool isPod() {
|
||||
#ifdef NDEBUG
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct isPodLike<AssertingVH<T> > {
|
||||
#ifdef NDEBUG
|
||||
static const bool value = true;
|
||||
#else
|
||||
static const bool value = false;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
/// TrackingVH - This is a value handle that tracks a Value (or Value subclass),
|
||||
/// even across RAUW operations.
|
||||
|
@ -186,14 +186,12 @@ class raw_ostream {
|
||||
// Inline fast path, particulary for constant strings where a sufficiently
|
||||
// smart compiler will simplify strlen.
|
||||
|
||||
this->operator<<(StringRef(Str));
|
||||
return *this;
|
||||
return this->operator<<(StringRef(Str));
|
||||
}
|
||||
|
||||
raw_ostream &operator<<(const std::string &Str) {
|
||||
// Avoid the fast path, it would only increase code size for a marginal win.
|
||||
write(Str.data(), Str.length());
|
||||
return *this;
|
||||
return write(Str.data(), Str.length());
|
||||
}
|
||||
|
||||
raw_ostream &operator<<(unsigned long N);
|
||||
@ -202,13 +200,11 @@ class raw_ostream {
|
||||
raw_ostream &operator<<(long long N);
|
||||
raw_ostream &operator<<(const void *P);
|
||||
raw_ostream &operator<<(unsigned int N) {
|
||||
this->operator<<(static_cast<unsigned long>(N));
|
||||
return *this;
|
||||
return this->operator<<(static_cast<unsigned long>(N));
|
||||
}
|
||||
|
||||
raw_ostream &operator<<(int N) {
|
||||
this->operator<<(static_cast<long>(N));
|
||||
return *this;
|
||||
return this->operator<<(static_cast<long>(N));
|
||||
}
|
||||
|
||||
raw_ostream &operator<<(double N);
|
||||
|
@ -17,13 +17,15 @@
|
||||
#ifndef LLVM_SUPPORT_TYPE_TRAITS_H
|
||||
#define LLVM_SUPPORT_TYPE_TRAITS_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
// This is actually the conforming implementation which works with abstract
|
||||
// classes. However, enough compilers have trouble with it that most will use
|
||||
// the one in boost/type_traits/object_traits.hpp. This implementation actually
|
||||
// works with VC7.0, but other interactions seem to fail when we use it.
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
||||
namespace dont_use
|
||||
{
|
||||
// These two functions should never be used. They are helpers to
|
||||
@ -48,6 +50,23 @@ struct is_class
|
||||
public:
|
||||
enum { value = sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)) };
|
||||
};
|
||||
|
||||
|
||||
/// isPodLike - This is a type trait that is used to determine whether a given
|
||||
/// type can be copied around with memcpy instead of running ctors etc.
|
||||
template <typename T>
|
||||
struct isPodLike {
|
||||
// If we don't know anything else, we can (at least) assume that all non-class
|
||||
// types are PODs.
|
||||
static const bool value = !is_class<T>::value;
|
||||
};
|
||||
|
||||
// std::pair's are pod-like if their elements are.
|
||||
template<typename T, typename U>
|
||||
struct isPodLike<std::pair<T, U> > {
|
||||
static const bool value = isPodLike<T>::value & isPodLike<U>::value;
|
||||
};
|
||||
|
||||
|
||||
/// \brief Metafunction that determines whether the two given types are
|
||||
/// equivalent.
|
||||
|
@ -20,7 +20,11 @@ namespace llvm {
|
||||
namespace sys {
|
||||
void MemoryFence();
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef long cas_flag;
|
||||
#else
|
||||
typedef uint32_t cas_flag;
|
||||
#endif
|
||||
cas_flag CompareAndSwap(volatile cas_flag* ptr,
|
||||
cas_flag new_value,
|
||||
cas_flag old_value);
|
||||
|
@ -118,14 +118,33 @@ typedef signed int ssize_t;
|
||||
#define INT32_MAX 2147483647
|
||||
#define INT32_MIN -2147483648
|
||||
#define UINT32_MAX 4294967295U
|
||||
#define INT8_C(C) C
|
||||
#define UINT8_C(C) C
|
||||
#define INT16_C(C) C
|
||||
#define UINT16_C(C) C
|
||||
#define INT32_C(C) C
|
||||
#define UINT32_C(C) C ## U
|
||||
#define INT64_C(C) ((int64_t) C ## LL)
|
||||
#define UINT64_C(C) ((uint64_t) C ## ULL)
|
||||
/* Certain compatibility updates to VC++ introduce the `cstdint'
|
||||
* header, which defines the INT*_C macros. On default installs they
|
||||
* are absent. */
|
||||
#ifndef INT8_C
|
||||
# define INT8_C(C) C
|
||||
#endif
|
||||
#ifndef UINT8_C
|
||||
# define UINT8_C(C) C
|
||||
#endif
|
||||
#ifndef INT16_C
|
||||
# define INT16_C(C) C
|
||||
#endif
|
||||
#ifndef UINT16_C
|
||||
# define UINT16_C(C) C
|
||||
#endif
|
||||
#ifndef INT32_C
|
||||
# define INT32_C(C) C
|
||||
#endif
|
||||
#ifndef UINT32_C
|
||||
# define UINT32_C(C) C ## U
|
||||
#endif
|
||||
#ifndef INT64_C
|
||||
# define INT64_C(C) ((int64_t) C ## LL)
|
||||
#endif
|
||||
#ifndef UINT64_C
|
||||
# define UINT64_C(C) ((uint64_t) C ## ULL)
|
||||
#endif
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* Set defaults for constants which we cannot find. */
|
||||
|
@ -36,8 +36,6 @@
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
|
||||
/* Note that this header's correct operation depends on __STDC_LIMIT_MACROS
|
||||
being defined. We would define it here, but in order to prevent Bad Things
|
||||
happening when system headers or C++ STL headers include stdint.h before we
|
||||
@ -89,40 +87,6 @@ typedef u_int64_t uint64_t;
|
||||
#define UINT32_MAX 4294967295U
|
||||
#endif
|
||||
|
||||
#else /* _MSC_VER */
|
||||
/* Visual C++ doesn't provide standard integer headers, but it does provide
|
||||
built-in data types. */
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <sys/types.h>
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed int ssize_t;
|
||||
#define INT8_MAX 127
|
||||
#define INT8_MIN -128
|
||||
#define UINT8_MAX 255
|
||||
#define INT16_MAX 32767
|
||||
#define INT16_MIN -32768
|
||||
#define UINT16_MAX 65535
|
||||
#define INT32_MAX 2147483647
|
||||
#define INT32_MIN -2147483648
|
||||
#define UINT32_MAX 4294967295U
|
||||
#define INT8_C(C) C
|
||||
#define UINT8_C(C) C
|
||||
#define INT16_C(C) C
|
||||
#define UINT16_C(C) C
|
||||
#define INT32_C(C) C
|
||||
#define UINT32_C(C) C ## U
|
||||
#define INT64_C(C) ((int64_t) C ## LL)
|
||||
#define UINT64_C(C) ((uint64_t) C ## ULL)
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
/* Set defaults for constants which we cannot find. */
|
||||
#if !defined(INT64_MAX)
|
||||
# define INT64_MAX 9223372036854775807LL
|
||||
|
@ -30,7 +30,6 @@ class Type;
|
||||
class IntegerType;
|
||||
class StructType;
|
||||
class StructLayout;
|
||||
class StructLayoutMap;
|
||||
class GlobalVariable;
|
||||
class LLVMContext;
|
||||
|
||||
@ -60,8 +59,6 @@ struct TargetAlignElem {
|
||||
unsigned char pref_align, uint32_t bit_width);
|
||||
/// Equality predicate
|
||||
bool operator==(const TargetAlignElem &rhs) const;
|
||||
/// output stream operator
|
||||
std::ostream &dump(std::ostream &os) const;
|
||||
};
|
||||
|
||||
class TargetData : public ImmutablePass {
|
||||
@ -86,7 +83,7 @@ class TargetData : public ImmutablePass {
|
||||
static const TargetAlignElem InvalidAlignmentElem;
|
||||
|
||||
// The StructType -> StructLayout map.
|
||||
mutable StructLayoutMap *LayoutMap;
|
||||
mutable void *LayoutMap;
|
||||
|
||||
//! Set/initialize target alignments
|
||||
void setAlignment(AlignTypeEnum align_type, unsigned char abi_align,
|
||||
@ -153,7 +150,7 @@ class TargetData : public ImmutablePass {
|
||||
/// The width is specified in bits.
|
||||
///
|
||||
bool isLegalInteger(unsigned Width) const {
|
||||
for (unsigned i = 0, e = LegalIntWidths.size(); i != e; ++i)
|
||||
for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i)
|
||||
if (LegalIntWidths[i] == Width)
|
||||
return true;
|
||||
return false;
|
||||
|
@ -26,6 +26,7 @@ class LiveVariables;
|
||||
class CalleeSavedInfo;
|
||||
class SDNode;
|
||||
class SelectionDAG;
|
||||
class MachineMemOperand;
|
||||
|
||||
template<class T> class SmallVectorImpl;
|
||||
|
||||
@ -182,11 +183,13 @@ class TargetInstrInfo {
|
||||
|
||||
/// hasLoadFromStackSlot - If the specified machine instruction has
|
||||
/// a load from a stack slot, return true along with the FrameIndex
|
||||
/// of the loaded stack slot. If not, return false. Unlike
|
||||
/// of the loaded stack slot and the machine mem operand containing
|
||||
/// the reference. If not, return false. Unlike
|
||||
/// isLoadFromStackSlot, this returns true for any instructions that
|
||||
/// loads from the stack. This is just a hint, as some cases may be
|
||||
/// missed.
|
||||
virtual bool hasLoadFromStackSlot(const MachineInstr *MI,
|
||||
const MachineMemOperand *&MMO,
|
||||
int &FrameIndex) const {
|
||||
return 0;
|
||||
}
|
||||
@ -205,17 +208,18 @@ class TargetInstrInfo {
|
||||
/// stack locations as well. This uses a heuristic so it isn't
|
||||
/// reliable for correctness.
|
||||
virtual unsigned isStoreToStackSlotPostFE(const MachineInstr *MI,
|
||||
int &FrameIndex) const {
|
||||
int &FrameIndex) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// hasStoreToStackSlot - If the specified machine instruction has a
|
||||
/// store to a stack slot, return true along with the FrameIndex of
|
||||
/// the loaded stack slot. If not, return false. Unlike
|
||||
/// isStoreToStackSlot, this returns true for any instructions that
|
||||
/// loads from the stack. This is just a hint, as some cases may be
|
||||
/// missed.
|
||||
/// the loaded stack slot and the machine mem operand containing the
|
||||
/// reference. If not, return false. Unlike isStoreToStackSlot,
|
||||
/// this returns true for any instructions that loads from the
|
||||
/// stack. This is just a hint, as some cases may be missed.
|
||||
virtual bool hasStoreToStackSlot(const MachineInstr *MI,
|
||||
const MachineMemOperand *&MMO,
|
||||
int &FrameIndex) const {
|
||||
return 0;
|
||||
}
|
||||
@ -282,11 +286,10 @@ class TargetInstrInfo {
|
||||
/// just return false, leaving TBB/FBB null.
|
||||
/// 2. If this block ends with only an unconditional branch, it sets TBB to be
|
||||
/// the destination block.
|
||||
/// 3. If this block ends with an conditional branch and it falls through to
|
||||
/// a successor block, it sets TBB to be the branch destination block and
|
||||
/// a list of operands that evaluate the condition. These
|
||||
/// operands can be passed to other TargetInstrInfo methods to create new
|
||||
/// branches.
|
||||
/// 3. If this block ends with a conditional branch and it falls through to a
|
||||
/// successor block, it sets TBB to be the branch destination block and a
|
||||
/// list of operands that evaluate the condition. These operands can be
|
||||
/// passed to other TargetInstrInfo methods to create new branches.
|
||||
/// 4. If this block ends with a conditional branch followed by an
|
||||
/// unconditional branch, it returns the 'true' destination in TBB, the
|
||||
/// 'false' destination in FBB, and a list of operands that evaluate the
|
||||
@ -461,14 +464,6 @@ class TargetInstrInfo {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// BlockHasNoFallThrough - Return true if the specified block does not
|
||||
/// fall-through into its successor block. This is primarily used when a
|
||||
/// branch is unanalyzable. It is useful for things like unconditional
|
||||
/// indirect branches (jump tables).
|
||||
virtual bool BlockHasNoFallThrough(const MachineBasicBlock &MBB) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ReverseBranchCondition - Reverses the branch condition of the specified
|
||||
/// condition list, returning false on success and true if it cannot be
|
||||
/// reversed.
|
||||
|
@ -857,12 +857,6 @@ class TargetLowering {
|
||||
virtual bool
|
||||
isGAPlusOffset(SDNode *N, GlobalValue* &GA, int64_t &Offset) const;
|
||||
|
||||
/// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a
|
||||
/// location that is 'Dist' units away from the location that the 'Base' load
|
||||
/// is loading from.
|
||||
bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes,
|
||||
int Dist, const MachineFrameInfo *MFI) const;
|
||||
|
||||
/// PerformDAGCombine - This method will be invoked for all target nodes and
|
||||
/// for any target-independent nodes that the target has registered with
|
||||
/// invoke it for.
|
||||
@ -978,7 +972,7 @@ class TargetLowering {
|
||||
/// not work with the with specified type and indicate what to do about it.
|
||||
void setLoadExtAction(unsigned ExtType, MVT VT,
|
||||
LegalizeAction Action) {
|
||||
assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE &&
|
||||
assert((unsigned)VT.SimpleTy*2 < 63 &&
|
||||
ExtType < array_lengthof(LoadExtActions) &&
|
||||
"Table isn't big enough!");
|
||||
LoadExtActions[ExtType] &= ~(uint64_t(3UL) << VT.SimpleTy*2);
|
||||
@ -990,7 +984,7 @@ class TargetLowering {
|
||||
void setTruncStoreAction(MVT ValVT, MVT MemVT,
|
||||
LegalizeAction Action) {
|
||||
assert((unsigned)ValVT.SimpleTy < array_lengthof(TruncStoreActions) &&
|
||||
(unsigned)MemVT.SimpleTy < MVT::LAST_VALUETYPE &&
|
||||
(unsigned)MemVT.SimpleTy*2 < 63 &&
|
||||
"Table isn't big enough!");
|
||||
TruncStoreActions[ValVT.SimpleTy] &= ~(uint64_t(3UL) << MemVT.SimpleTy*2);
|
||||
TruncStoreActions[ValVT.SimpleTy] |= (uint64_t)Action << MemVT.SimpleTy*2;
|
||||
|
@ -299,7 +299,7 @@ class TargetRegisterInfo {
|
||||
/// FirstVirtualRegister - This is the first register number that is
|
||||
/// considered to be a 'virtual' register, which is part of the SSA
|
||||
/// namespace. This must be the same for all targets, which means that each
|
||||
/// target is limited to 1024 registers.
|
||||
/// target is limited to this fixed number of registers.
|
||||
FirstVirtualRegister = 1024
|
||||
};
|
||||
|
||||
|
@ -27,6 +27,7 @@ add_llvm_library(LLVMAnalysis
|
||||
LoopPass.cpp
|
||||
MemoryBuiltins.cpp
|
||||
MemoryDependenceAnalysis.cpp
|
||||
PHITransAddr.cpp
|
||||
PointerTracking.cpp
|
||||
PostDominators.cpp
|
||||
ProfileEstimatorPass.cpp
|
||||
|
@ -25,6 +25,16 @@
|
||||
#include "llvm/Support/CallSite.h"
|
||||
using namespace llvm;
|
||||
|
||||
/// As its comment mentions, PointerMayBeCaptured can be expensive.
|
||||
/// However, it's not easy for BasicAA to cache the result, because
|
||||
/// it's an ImmutablePass. To work around this, bound queries at a
|
||||
/// fixed number of uses.
|
||||
///
|
||||
/// TODO: Write a new FunctionPass AliasAnalysis so that it can keep
|
||||
/// a cache. Then we can move the code from BasicAliasAnalysis into
|
||||
/// that path, and remove this threshold.
|
||||
static int const Threshold = 20;
|
||||
|
||||
/// PointerMayBeCaptured - Return true if this pointer value may be captured
|
||||
/// by the enclosing function (which is required to exist). This routine can
|
||||
/// be expensive, so consider caching the results. The boolean ReturnCaptures
|
||||
@ -35,11 +45,17 @@ using namespace llvm;
|
||||
bool llvm::PointerMayBeCaptured(const Value *V,
|
||||
bool ReturnCaptures, bool StoreCaptures) {
|
||||
assert(isa<PointerType>(V->getType()) && "Capture is for pointers only!");
|
||||
SmallVector<Use*, 16> Worklist;
|
||||
SmallSet<Use*, 16> Visited;
|
||||
SmallVector<Use*, Threshold> Worklist;
|
||||
SmallSet<Use*, Threshold> Visited;
|
||||
int Count = 0;
|
||||
|
||||
for (Value::use_const_iterator UI = V->use_begin(), UE = V->use_end();
|
||||
UI != UE; ++UI) {
|
||||
// If there are lots of uses, conservatively say that the value
|
||||
// is captured to avoid taking too much compile time.
|
||||
if (Count++ >= Threshold)
|
||||
return true;
|
||||
|
||||
Use *U = &UI.getUse();
|
||||
Visited.insert(U);
|
||||
Worklist.push_back(U);
|
||||
|
@ -432,7 +432,7 @@ Constant *llvm::ConstantFoldLoadFromConstPtr(Constant *C,
|
||||
// Instead of loading constant c string, use corresponding integer value
|
||||
// directly if string length is small enough.
|
||||
std::string Str;
|
||||
if (TD && GetConstantStringInfo(CE->getOperand(0), Str) && !Str.empty()) {
|
||||
if (TD && GetConstantStringInfo(CE, Str) && !Str.empty()) {
|
||||
unsigned StrLen = Str.length();
|
||||
const Type *Ty = cast<PointerType>(CE->getType())->getElementType();
|
||||
unsigned NumBits = Ty->getPrimitiveSizeInBits();
|
||||
@ -569,9 +569,16 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps,
|
||||
SmallVector<Constant*, 32> NewIdxs;
|
||||
do {
|
||||
if (const SequentialType *ATy = dyn_cast<SequentialType>(Ty)) {
|
||||
// The only pointer indexing we'll do is on the first index of the GEP.
|
||||
if (isa<PointerType>(ATy) && !NewIdxs.empty())
|
||||
break;
|
||||
if (isa<PointerType>(ATy)) {
|
||||
// The only pointer indexing we'll do is on the first index of the GEP.
|
||||
if (!NewIdxs.empty())
|
||||
break;
|
||||
|
||||
// Only handle pointers to sized types, not pointers to functions.
|
||||
if (!ATy->getElementType()->isSized())
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Determine which element of the array the offset points into.
|
||||
APInt ElemSize(BitWidth, TD->getTypeAllocSize(ATy->getElementType()));
|
||||
if (ElemSize == 0)
|
||||
|
@ -866,7 +866,9 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
|
||||
DICompileUnit CompileUnit,
|
||||
unsigned LineNo, DIType Type,
|
||||
bool isLocalToUnit,
|
||||
bool isDefinition) {
|
||||
bool isDefinition,
|
||||
unsigned VK, unsigned VIndex,
|
||||
DIType ContainingType) {
|
||||
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(dwarf::DW_TAG_subprogram),
|
||||
@ -879,9 +881,38 @@ DISubprogram DIFactory::CreateSubprogram(DIDescriptor Context,
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
|
||||
Type.getNode(),
|
||||
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
|
||||
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition)
|
||||
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK),
|
||||
ConstantInt::get(Type::getInt32Ty(VMContext), VIndex),
|
||||
ContainingType.getNode()
|
||||
};
|
||||
return DISubprogram(MDNode::get(VMContext, &Elts[0], 11));
|
||||
return DISubprogram(MDNode::get(VMContext, &Elts[0], 14));
|
||||
}
|
||||
|
||||
/// CreateSubprogramDefinition - Create new subprogram descriptor for the
|
||||
/// given declaration.
|
||||
DISubprogram DIFactory::CreateSubprogramDefinition(DISubprogram &SPDeclaration) {
|
||||
if (SPDeclaration.isDefinition())
|
||||
return DISubprogram(SPDeclaration.getNode());
|
||||
|
||||
MDNode *DeclNode = SPDeclaration.getNode();
|
||||
Value *Elts[] = {
|
||||
GetTagConstant(dwarf::DW_TAG_subprogram),
|
||||
llvm::Constant::getNullValue(Type::getInt32Ty(VMContext)),
|
||||
DeclNode->getElement(2), // Context
|
||||
DeclNode->getElement(3), // Name
|
||||
DeclNode->getElement(4), // DisplayName
|
||||
DeclNode->getElement(5), // LinkageName
|
||||
DeclNode->getElement(6), // CompileUnit
|
||||
DeclNode->getElement(7), // LineNo
|
||||
DeclNode->getElement(8), // Type
|
||||
DeclNode->getElement(9), // isLocalToUnit
|
||||
ConstantInt::get(Type::getInt1Ty(VMContext), true),
|
||||
DeclNode->getElement(11), // Virtuality
|
||||
DeclNode->getElement(12), // VIndex
|
||||
DeclNode->getElement(13) // Containting Type
|
||||
};
|
||||
return DISubprogram(MDNode::get(VMContext, &Elts[0], 14));
|
||||
}
|
||||
|
||||
/// CreateGlobalVariable - Create a new descriptor for the specified global.
|
||||
@ -1019,6 +1050,37 @@ Instruction *DIFactory::InsertDeclare(Value *Storage, DIVariable D,
|
||||
return CallInst::Create(DeclareFn, Args, Args+2, "", InsertAtEnd);
|
||||
}
|
||||
|
||||
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, Value *Offset,
|
||||
DIVariable D,
|
||||
Instruction *InsertBefore) {
|
||||
assert(V && "no value passed to dbg.value");
|
||||
assert(Offset->getType() == Type::getInt64Ty(V->getContext()) &&
|
||||
"offset must be i64");
|
||||
if (!ValueFn)
|
||||
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
|
||||
|
||||
Value *Elts[] = { V };
|
||||
Value *Args[] = { MDNode::get(V->getContext(), Elts, 1), Offset,
|
||||
D.getNode() };
|
||||
return CallInst::Create(ValueFn, Args, Args+3, "", InsertBefore);
|
||||
}
|
||||
|
||||
/// InsertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
|
||||
Instruction *DIFactory::InsertDbgValueIntrinsic(Value *V, Value *Offset,
|
||||
DIVariable D,
|
||||
BasicBlock *InsertAtEnd) {
|
||||
assert(V && "no value passed to dbg.value");
|
||||
assert(Offset->getType() == Type::getInt64Ty(V->getContext()) &&
|
||||
"offset must be i64");
|
||||
if (!ValueFn)
|
||||
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
|
||||
|
||||
Value *Elts[] = { V };
|
||||
Value *Args[] = { MDNode::get(V->getContext(), Elts, 1), Offset,
|
||||
D.getNode() };
|
||||
return CallInst::Create(ValueFn, Args, Args+3, "", InsertAtEnd);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DebugInfoFinder implementations.
|
||||
|
@ -121,8 +121,6 @@ namespace {
|
||||
|
||||
return *LHS == *RHS;
|
||||
}
|
||||
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
|
||||
class Andersens : public ModulePass, public AliasAnalysis,
|
||||
|
@ -53,7 +53,7 @@ static bool containsAddRecFromDifferentLoop(const SCEV *S, Loop *L) {
|
||||
if (newLoop == L)
|
||||
return false;
|
||||
// if newLoop is an outer loop of L, this is OK.
|
||||
if (!LoopInfo::isNotAlreadyContainedIn(L, newLoop))
|
||||
if (newLoop->contains(L->getHeader()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -307,6 +307,7 @@ bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) {
|
||||
for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I)
|
||||
AddUsersIfInteresting(I);
|
||||
|
||||
Processed.clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -369,7 +370,7 @@ void IVUsers::dump() const {
|
||||
void IVUsers::releaseMemory() {
|
||||
IVUsesByStride.clear();
|
||||
StrideOrder.clear();
|
||||
Processed.clear();
|
||||
IVUses.clear();
|
||||
}
|
||||
|
||||
void IVStrideUse::deleted() {
|
||||
|
@ -316,12 +316,12 @@ bool Loop::hasDedicatedExits() const {
|
||||
|
||||
/// getUniqueExitBlocks - Return all unique successor blocks of this loop.
|
||||
/// These are the blocks _outside of the current loop_ which are branched to.
|
||||
/// This assumes that loop is in canonical form.
|
||||
/// This assumes that loop exits are in canonical form.
|
||||
///
|
||||
void
|
||||
Loop::getUniqueExitBlocks(SmallVectorImpl<BasicBlock *> &ExitBlocks) const {
|
||||
assert(isLoopSimplifyForm() &&
|
||||
"getUniqueExitBlocks assumes the loop is in canonical form!");
|
||||
assert(hasDedicatedExits() &&
|
||||
"getUniqueExitBlocks assumes the loop has canonical form exits!");
|
||||
|
||||
// Sort the blocks vector so that we can use binary search to do quick
|
||||
// lookups.
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/MemoryBuiltins.h"
|
||||
#include "llvm/Analysis/PHITransAddr.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/Support/PredIteratorCache.h"
|
||||
@ -172,7 +173,7 @@ MemDepResult MemoryDependenceAnalysis::
|
||||
getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
|
||||
BasicBlock::iterator ScanIt, BasicBlock *BB) {
|
||||
|
||||
Value *invariantTag = 0;
|
||||
Value *InvariantTag = 0;
|
||||
|
||||
// Walk backwards through the basic block, looking for dependencies.
|
||||
while (ScanIt != BB->begin()) {
|
||||
@ -180,34 +181,36 @@ getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
|
||||
|
||||
// If we're in an invariant region, no dependencies can be found before
|
||||
// we pass an invariant-begin marker.
|
||||
if (invariantTag == Inst) {
|
||||
invariantTag = 0;
|
||||
if (InvariantTag == Inst) {
|
||||
InvariantTag = 0;
|
||||
continue;
|
||||
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
|
||||
}
|
||||
|
||||
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(Inst)) {
|
||||
// Debug intrinsics don't cause dependences.
|
||||
if (isa<DbgInfoIntrinsic>(Inst)) continue;
|
||||
|
||||
// If we pass an invariant-end marker, then we've just entered an
|
||||
// invariant region and can start ignoring dependencies.
|
||||
if (II->getIntrinsicID() == Intrinsic::invariant_end) {
|
||||
uint64_t invariantSize = ~0ULL;
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(II->getOperand(2)))
|
||||
invariantSize = CI->getZExtValue();
|
||||
|
||||
AliasAnalysis::AliasResult R =
|
||||
AA->alias(II->getOperand(3), invariantSize, MemPtr, MemSize);
|
||||
// FIXME: This only considers queries directly on the invariant-tagged
|
||||
// pointer, not on query pointers that are indexed off of them. It'd
|
||||
// be nice to handle that at some point.
|
||||
AliasAnalysis::AliasResult R =
|
||||
AA->alias(II->getOperand(3), ~0U, MemPtr, ~0U);
|
||||
if (R == AliasAnalysis::MustAlias) {
|
||||
invariantTag = II->getOperand(1);
|
||||
InvariantTag = II->getOperand(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we reach a lifetime begin or end marker, then the query ends here
|
||||
// because the value is undefined.
|
||||
} else if (II->getIntrinsicID() == Intrinsic::lifetime_start ||
|
||||
II->getIntrinsicID() == Intrinsic::lifetime_end) {
|
||||
uint64_t invariantSize = ~0ULL;
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(II->getOperand(1)))
|
||||
invariantSize = CI->getZExtValue();
|
||||
|
||||
} else if (II->getIntrinsicID() == Intrinsic::lifetime_start) {
|
||||
// FIXME: This only considers queries directly on the invariant-tagged
|
||||
// pointer, not on query pointers that are indexed off of them. It'd
|
||||
// be nice to handle that at some point.
|
||||
AliasAnalysis::AliasResult R =
|
||||
AA->alias(II->getOperand(2), invariantSize, MemPtr, MemSize);
|
||||
AA->alias(II->getOperand(2), ~0U, MemPtr, ~0U);
|
||||
if (R == AliasAnalysis::MustAlias)
|
||||
return MemDepResult::getDef(II);
|
||||
}
|
||||
@ -215,10 +218,7 @@ getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
|
||||
|
||||
// If we're querying on a load and we're in an invariant region, we're done
|
||||
// at this point. Nothing a load depends on can live in an invariant region.
|
||||
if (isLoad && invariantTag) continue;
|
||||
|
||||
// Debug intrinsics don't cause dependences.
|
||||
if (isa<DbgInfoIntrinsic>(Inst)) continue;
|
||||
if (isLoad && InvariantTag) continue;
|
||||
|
||||
// Values depend on loads if the pointers are must aliased. This means that
|
||||
// a load depends on another must aliased load from the same value.
|
||||
@ -243,7 +243,7 @@ getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
|
||||
if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) {
|
||||
// There can't be stores to the value we care about inside an
|
||||
// invariant region.
|
||||
if (invariantTag) continue;
|
||||
if (InvariantTag) continue;
|
||||
|
||||
// If alias analysis can tell that this store is guaranteed to not modify
|
||||
// the query pointer, ignore it. Use getModRefInfo to handle cases where
|
||||
@ -292,7 +292,7 @@ getPointerDependencyFrom(Value *MemPtr, uint64_t MemSize, bool isLoad,
|
||||
case AliasAnalysis::Mod:
|
||||
// If we're in an invariant region, we can ignore calls that ONLY
|
||||
// modify the pointer.
|
||||
if (invariantTag) continue;
|
||||
if (InvariantTag) continue;
|
||||
return MemDepResult::getClobber(Inst);
|
||||
case AliasAnalysis::Ref:
|
||||
// If the call is known to never store to the pointer, and if this is a
|
||||
@ -374,21 +374,22 @@ MemDepResult MemoryDependenceAnalysis::getDependency(Instruction *QueryInst) {
|
||||
IntrinsicID = II->getIntrinsicID();
|
||||
|
||||
switch (IntrinsicID) {
|
||||
case Intrinsic::lifetime_start:
|
||||
case Intrinsic::lifetime_end:
|
||||
case Intrinsic::invariant_start:
|
||||
MemPtr = QueryInst->getOperand(2);
|
||||
MemSize = cast<ConstantInt>(QueryInst->getOperand(1))->getZExtValue();
|
||||
break;
|
||||
case Intrinsic::invariant_end:
|
||||
MemPtr = QueryInst->getOperand(3);
|
||||
MemSize = cast<ConstantInt>(QueryInst->getOperand(2))->getZExtValue();
|
||||
break;
|
||||
default:
|
||||
CallSite QueryCS = CallSite::get(QueryInst);
|
||||
bool isReadOnly = AA->onlyReadsMemory(QueryCS);
|
||||
LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos,
|
||||
QueryParent);
|
||||
case Intrinsic::lifetime_start:
|
||||
case Intrinsic::lifetime_end:
|
||||
case Intrinsic::invariant_start:
|
||||
MemPtr = QueryInst->getOperand(2);
|
||||
MemSize = cast<ConstantInt>(QueryInst->getOperand(1))->getZExtValue();
|
||||
break;
|
||||
case Intrinsic::invariant_end:
|
||||
MemPtr = QueryInst->getOperand(3);
|
||||
MemSize = cast<ConstantInt>(QueryInst->getOperand(2))->getZExtValue();
|
||||
break;
|
||||
default:
|
||||
CallSite QueryCS = CallSite::get(QueryInst);
|
||||
bool isReadOnly = AA->onlyReadsMemory(QueryCS);
|
||||
LocalCache = getCallSiteDependencyFrom(QueryCS, isReadOnly, ScanPos,
|
||||
QueryParent);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Non-memory instruction.
|
||||
@ -421,7 +422,7 @@ static void AssertSorted(MemoryDependenceAnalysis::NonLocalDepInfo &Cache,
|
||||
if (Count == 0) return;
|
||||
|
||||
for (unsigned i = 1; i != unsigned(Count); ++i)
|
||||
assert(Cache[i-1] <= Cache[i] && "Cache isn't sorted!");
|
||||
assert(!(Cache[i] < Cache[i-1]) && "Cache isn't sorted!");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -462,8 +463,8 @@ MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) {
|
||||
// determine what is dirty, seeding our initial DirtyBlocks worklist.
|
||||
for (NonLocalDepInfo::iterator I = Cache.begin(), E = Cache.end();
|
||||
I != E; ++I)
|
||||
if (I->second.isDirty())
|
||||
DirtyBlocks.push_back(I->first);
|
||||
if (I->getResult().isDirty())
|
||||
DirtyBlocks.push_back(I->getBB());
|
||||
|
||||
// Sort the cache so that we can do fast binary search lookups below.
|
||||
std::sort(Cache.begin(), Cache.end());
|
||||
@ -501,27 +502,27 @@ MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) {
|
||||
DEBUG(AssertSorted(Cache, NumSortedEntries));
|
||||
NonLocalDepInfo::iterator Entry =
|
||||
std::upper_bound(Cache.begin(), Cache.begin()+NumSortedEntries,
|
||||
std::make_pair(DirtyBB, MemDepResult()));
|
||||
if (Entry != Cache.begin() && prior(Entry)->first == DirtyBB)
|
||||
NonLocalDepEntry(DirtyBB));
|
||||
if (Entry != Cache.begin() && prior(Entry)->getBB() == DirtyBB)
|
||||
--Entry;
|
||||
|
||||
MemDepResult *ExistingResult = 0;
|
||||
NonLocalDepEntry *ExistingResult = 0;
|
||||
if (Entry != Cache.begin()+NumSortedEntries &&
|
||||
Entry->first == DirtyBB) {
|
||||
Entry->getBB() == DirtyBB) {
|
||||
// If we already have an entry, and if it isn't already dirty, the block
|
||||
// is done.
|
||||
if (!Entry->second.isDirty())
|
||||
if (!Entry->getResult().isDirty())
|
||||
continue;
|
||||
|
||||
// Otherwise, remember this slot so we can update the value.
|
||||
ExistingResult = &Entry->second;
|
||||
ExistingResult = &*Entry;
|
||||
}
|
||||
|
||||
// If the dirty entry has a pointer, start scanning from it so we don't have
|
||||
// to rescan the entire block.
|
||||
BasicBlock::iterator ScanPos = DirtyBB->end();
|
||||
if (ExistingResult) {
|
||||
if (Instruction *Inst = ExistingResult->getInst()) {
|
||||
if (Instruction *Inst = ExistingResult->getResult().getInst()) {
|
||||
ScanPos = Inst;
|
||||
// We're removing QueryInst's use of Inst.
|
||||
RemoveFromReverseMap(ReverseNonLocalDeps, Inst,
|
||||
@ -545,9 +546,9 @@ MemoryDependenceAnalysis::getNonLocalCallDependency(CallSite QueryCS) {
|
||||
// If we had a dirty entry for the block, update it. Otherwise, just add
|
||||
// a new entry.
|
||||
if (ExistingResult)
|
||||
*ExistingResult = Dep;
|
||||
ExistingResult->setResult(Dep, 0);
|
||||
else
|
||||
Cache.push_back(std::make_pair(DirtyBB, Dep));
|
||||
Cache.push_back(NonLocalDepEntry(DirtyBB, Dep, 0));
|
||||
|
||||
// If the block has a dependency (i.e. it isn't completely transparent to
|
||||
// the value), remember the association!
|
||||
@ -587,17 +588,20 @@ getNonLocalPointerDependency(Value *Pointer, bool isLoad, BasicBlock *FromBB,
|
||||
const Type *EltTy = cast<PointerType>(Pointer->getType())->getElementType();
|
||||
uint64_t PointeeSize = AA->getTypeStoreSize(EltTy);
|
||||
|
||||
PHITransAddr Address(Pointer, TD);
|
||||
|
||||
// This is the set of blocks we've inspected, and the pointer we consider in
|
||||
// each block. Because of critical edges, we currently bail out if querying
|
||||
// a block with multiple different pointers. This can happen during PHI
|
||||
// translation.
|
||||
DenseMap<BasicBlock*, Value*> Visited;
|
||||
if (!getNonLocalPointerDepFromBB(Pointer, PointeeSize, isLoad, FromBB,
|
||||
if (!getNonLocalPointerDepFromBB(Address, PointeeSize, isLoad, FromBB,
|
||||
Result, Visited, true))
|
||||
return;
|
||||
Result.clear();
|
||||
Result.push_back(std::make_pair(FromBB,
|
||||
MemDepResult::getClobber(FromBB->begin())));
|
||||
Result.push_back(NonLocalDepEntry(FromBB,
|
||||
MemDepResult::getClobber(FromBB->begin()),
|
||||
Pointer));
|
||||
}
|
||||
|
||||
/// GetNonLocalInfoForBlock - Compute the memdep value for BB with
|
||||
@ -613,30 +617,30 @@ GetNonLocalInfoForBlock(Value *Pointer, uint64_t PointeeSize,
|
||||
// the cache set. If so, find it.
|
||||
NonLocalDepInfo::iterator Entry =
|
||||
std::upper_bound(Cache->begin(), Cache->begin()+NumSortedEntries,
|
||||
std::make_pair(BB, MemDepResult()));
|
||||
if (Entry != Cache->begin() && prior(Entry)->first == BB)
|
||||
NonLocalDepEntry(BB));
|
||||
if (Entry != Cache->begin() && (Entry-1)->getBB() == BB)
|
||||
--Entry;
|
||||
|
||||
MemDepResult *ExistingResult = 0;
|
||||
if (Entry != Cache->begin()+NumSortedEntries && Entry->first == BB)
|
||||
ExistingResult = &Entry->second;
|
||||
NonLocalDepEntry *ExistingResult = 0;
|
||||
if (Entry != Cache->begin()+NumSortedEntries && Entry->getBB() == BB)
|
||||
ExistingResult = &*Entry;
|
||||
|
||||
// If we have a cached entry, and it is non-dirty, use it as the value for
|
||||
// this dependency.
|
||||
if (ExistingResult && !ExistingResult->isDirty()) {
|
||||
if (ExistingResult && !ExistingResult->getResult().isDirty()) {
|
||||
++NumCacheNonLocalPtr;
|
||||
return *ExistingResult;
|
||||
return ExistingResult->getResult();
|
||||
}
|
||||
|
||||
// Otherwise, we have to scan for the value. If we have a dirty cache
|
||||
// entry, start scanning from its position, otherwise we scan from the end
|
||||
// of the block.
|
||||
BasicBlock::iterator ScanPos = BB->end();
|
||||
if (ExistingResult && ExistingResult->getInst()) {
|
||||
assert(ExistingResult->getInst()->getParent() == BB &&
|
||||
if (ExistingResult && ExistingResult->getResult().getInst()) {
|
||||
assert(ExistingResult->getResult().getInst()->getParent() == BB &&
|
||||
"Instruction invalidated?");
|
||||
++NumCacheDirtyNonLocalPtr;
|
||||
ScanPos = ExistingResult->getInst();
|
||||
ScanPos = ExistingResult->getResult().getInst();
|
||||
|
||||
// Eliminating the dirty entry from 'Cache', so update the reverse info.
|
||||
ValueIsLoadPair CacheKey(Pointer, isLoad);
|
||||
@ -652,9 +656,9 @@ GetNonLocalInfoForBlock(Value *Pointer, uint64_t PointeeSize,
|
||||
// If we had a dirty entry for the block, update it. Otherwise, just add
|
||||
// a new entry.
|
||||
if (ExistingResult)
|
||||
*ExistingResult = Dep;
|
||||
ExistingResult->setResult(Dep, Pointer);
|
||||
else
|
||||
Cache->push_back(std::make_pair(BB, Dep));
|
||||
Cache->push_back(NonLocalDepEntry(BB, Dep, Pointer));
|
||||
|
||||
// If the block has a dependency (i.e. it isn't completely transparent to
|
||||
// the value), remember the reverse association because we just added it
|
||||
@ -683,7 +687,7 @@ SortNonLocalDepInfoCache(MemoryDependenceAnalysis::NonLocalDepInfo &Cache,
|
||||
break;
|
||||
case 2: {
|
||||
// Two new entries, insert the last one into place.
|
||||
MemoryDependenceAnalysis::NonLocalDepEntry Val = Cache.back();
|
||||
NonLocalDepEntry Val = Cache.back();
|
||||
Cache.pop_back();
|
||||
MemoryDependenceAnalysis::NonLocalDepInfo::iterator Entry =
|
||||
std::upper_bound(Cache.begin(), Cache.end()-1, Val);
|
||||
@ -693,7 +697,7 @@ SortNonLocalDepInfoCache(MemoryDependenceAnalysis::NonLocalDepInfo &Cache,
|
||||
case 1:
|
||||
// One new entry, Just insert the new value at the appropriate position.
|
||||
if (Cache.size() != 1) {
|
||||
MemoryDependenceAnalysis::NonLocalDepEntry Val = Cache.back();
|
||||
NonLocalDepEntry Val = Cache.back();
|
||||
Cache.pop_back();
|
||||
MemoryDependenceAnalysis::NonLocalDepInfo::iterator Entry =
|
||||
std::upper_bound(Cache.begin(), Cache.end(), Val);
|
||||
@ -707,275 +711,6 @@ SortNonLocalDepInfoCache(MemoryDependenceAnalysis::NonLocalDepInfo &Cache,
|
||||
}
|
||||
}
|
||||
|
||||
/// isPHITranslatable - Return true if the specified computation is derived from
|
||||
/// a PHI node in the current block and if it is simple enough for us to handle.
|
||||
static bool isPHITranslatable(Instruction *Inst) {
|
||||
if (isa<PHINode>(Inst))
|
||||
return true;
|
||||
|
||||
// We can handle bitcast of a PHI, but the PHI needs to be in the same block
|
||||
// as the bitcast.
|
||||
if (BitCastInst *BC = dyn_cast<BitCastInst>(Inst)) {
|
||||
Instruction *OpI = dyn_cast<Instruction>(BC->getOperand(0));
|
||||
if (OpI == 0 || OpI->getParent() != Inst->getParent())
|
||||
return true;
|
||||
return isPHITranslatable(OpI);
|
||||
}
|
||||
|
||||
// We can translate a GEP if all of its operands defined in this block are phi
|
||||
// translatable.
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
|
||||
for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) {
|
||||
Instruction *OpI = dyn_cast<Instruction>(GEP->getOperand(i));
|
||||
if (OpI == 0 || OpI->getParent() != Inst->getParent())
|
||||
continue;
|
||||
|
||||
if (!isPHITranslatable(OpI))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Inst->getOpcode() == Instruction::Add &&
|
||||
isa<ConstantInt>(Inst->getOperand(1))) {
|
||||
Instruction *OpI = dyn_cast<Instruction>(Inst->getOperand(0));
|
||||
if (OpI == 0 || OpI->getParent() != Inst->getParent())
|
||||
return true;
|
||||
return isPHITranslatable(OpI);
|
||||
}
|
||||
|
||||
// cerr << "MEMDEP: Could not PHI translate: " << *Pointer;
|
||||
// if (isa<BitCastInst>(PtrInst) || isa<GetElementPtrInst>(PtrInst))
|
||||
// cerr << "OP:\t\t\t\t" << *PtrInst->getOperand(0);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// GetPHITranslatedValue - Given a computation that satisfied the
|
||||
/// isPHITranslatable predicate, see if we can translate the computation into
|
||||
/// the specified predecessor block. If so, return that value.
|
||||
Value *MemoryDependenceAnalysis::
|
||||
GetPHITranslatedValue(Value *InVal, BasicBlock *CurBB, BasicBlock *Pred,
|
||||
const TargetData *TD) const {
|
||||
// If the input value is not an instruction, or if it is not defined in CurBB,
|
||||
// then we don't need to phi translate it.
|
||||
Instruction *Inst = dyn_cast<Instruction>(InVal);
|
||||
if (Inst == 0 || Inst->getParent() != CurBB)
|
||||
return InVal;
|
||||
|
||||
if (PHINode *PN = dyn_cast<PHINode>(Inst))
|
||||
return PN->getIncomingValueForBlock(Pred);
|
||||
|
||||
// Handle bitcast of PHI.
|
||||
if (BitCastInst *BC = dyn_cast<BitCastInst>(Inst)) {
|
||||
// PHI translate the input operand.
|
||||
Value *PHIIn = GetPHITranslatedValue(BC->getOperand(0), CurBB, Pred, TD);
|
||||
if (PHIIn == 0) return 0;
|
||||
|
||||
// Constants are trivial to phi translate.
|
||||
if (Constant *C = dyn_cast<Constant>(PHIIn))
|
||||
return ConstantExpr::getBitCast(C, BC->getType());
|
||||
|
||||
// Otherwise we have to see if a bitcasted version of the incoming pointer
|
||||
// is available. If so, we can use it, otherwise we have to fail.
|
||||
for (Value::use_iterator UI = PHIIn->use_begin(), E = PHIIn->use_end();
|
||||
UI != E; ++UI) {
|
||||
if (BitCastInst *BCI = dyn_cast<BitCastInst>(*UI))
|
||||
if (BCI->getType() == BC->getType())
|
||||
return BCI;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle getelementptr with at least one PHI translatable operand.
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
|
||||
SmallVector<Value*, 8> GEPOps;
|
||||
BasicBlock *CurBB = GEP->getParent();
|
||||
for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) {
|
||||
Value *GEPOp = GEP->getOperand(i);
|
||||
// No PHI translation is needed of operands whose values are live in to
|
||||
// the predecessor block.
|
||||
if (!isa<Instruction>(GEPOp) ||
|
||||
cast<Instruction>(GEPOp)->getParent() != CurBB) {
|
||||
GEPOps.push_back(GEPOp);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the operand is a phi node, do phi translation.
|
||||
Value *InOp = GetPHITranslatedValue(GEPOp, CurBB, Pred, TD);
|
||||
if (InOp == 0) return 0;
|
||||
|
||||
GEPOps.push_back(InOp);
|
||||
}
|
||||
|
||||
// Simplify the GEP to handle 'gep x, 0' -> x etc.
|
||||
if (Value *V = SimplifyGEPInst(&GEPOps[0], GEPOps.size(), TD))
|
||||
return V;
|
||||
|
||||
// Scan to see if we have this GEP available.
|
||||
Value *APHIOp = GEPOps[0];
|
||||
for (Value::use_iterator UI = APHIOp->use_begin(), E = APHIOp->use_end();
|
||||
UI != E; ++UI) {
|
||||
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*UI))
|
||||
if (GEPI->getType() == GEP->getType() &&
|
||||
GEPI->getNumOperands() == GEPOps.size() &&
|
||||
GEPI->getParent()->getParent() == CurBB->getParent()) {
|
||||
bool Mismatch = false;
|
||||
for (unsigned i = 0, e = GEPOps.size(); i != e; ++i)
|
||||
if (GEPI->getOperand(i) != GEPOps[i]) {
|
||||
Mismatch = true;
|
||||
break;
|
||||
}
|
||||
if (!Mismatch)
|
||||
return GEPI;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle add with a constant RHS.
|
||||
if (Inst->getOpcode() == Instruction::Add &&
|
||||
isa<ConstantInt>(Inst->getOperand(1))) {
|
||||
// PHI translate the LHS.
|
||||
Value *LHS;
|
||||
Constant *RHS = cast<ConstantInt>(Inst->getOperand(1));
|
||||
Instruction *OpI = dyn_cast<Instruction>(Inst->getOperand(0));
|
||||
bool isNSW = cast<BinaryOperator>(Inst)->hasNoSignedWrap();
|
||||
bool isNUW = cast<BinaryOperator>(Inst)->hasNoUnsignedWrap();
|
||||
|
||||
if (OpI == 0 || OpI->getParent() != Inst->getParent())
|
||||
LHS = Inst->getOperand(0);
|
||||
else {
|
||||
LHS = GetPHITranslatedValue(Inst->getOperand(0), CurBB, Pred, TD);
|
||||
if (LHS == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the PHI translated LHS is an add of a constant, fold the immediates.
|
||||
if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(LHS))
|
||||
if (BOp->getOpcode() == Instruction::Add)
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(BOp->getOperand(1))) {
|
||||
LHS = BOp->getOperand(0);
|
||||
RHS = ConstantExpr::getAdd(RHS, CI);
|
||||
isNSW = isNUW = false;
|
||||
}
|
||||
|
||||
// See if the add simplifies away.
|
||||
if (Value *Res = SimplifyAddInst(LHS, RHS, isNSW, isNUW, TD))
|
||||
return Res;
|
||||
|
||||
// Otherwise, see if we have this add available somewhere.
|
||||
for (Value::use_iterator UI = LHS->use_begin(), E = LHS->use_end();
|
||||
UI != E; ++UI) {
|
||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(*UI))
|
||||
if (BO->getOperand(0) == LHS && BO->getOperand(1) == RHS &&
|
||||
BO->getParent()->getParent() == CurBB->getParent())
|
||||
return BO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// GetAvailablePHITranslatePointer - Return the value computed by
|
||||
/// PHITranslatePointer if it dominates PredBB, otherwise return null.
|
||||
Value *MemoryDependenceAnalysis::
|
||||
GetAvailablePHITranslatedValue(Value *V,
|
||||
BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const TargetData *TD,
|
||||
const DominatorTree &DT) const {
|
||||
// See if PHI translation succeeds.
|
||||
V = GetPHITranslatedValue(V, CurBB, PredBB, TD);
|
||||
if (V == 0) return 0;
|
||||
|
||||
// Make sure the value is live in the predecessor.
|
||||
if (Instruction *Inst = dyn_cast_or_null<Instruction>(V))
|
||||
if (!DT.dominates(Inst->getParent(), PredBB))
|
||||
return 0;
|
||||
return V;
|
||||
}
|
||||
|
||||
|
||||
/// InsertPHITranslatedPointer - Insert a computation of the PHI translated
|
||||
/// version of 'V' for the edge PredBB->CurBB into the end of the PredBB
|
||||
/// block. All newly created instructions are added to the NewInsts list.
|
||||
///
|
||||
Value *MemoryDependenceAnalysis::
|
||||
InsertPHITranslatedPointer(Value *InVal, BasicBlock *CurBB,
|
||||
BasicBlock *PredBB, const TargetData *TD,
|
||||
const DominatorTree &DT,
|
||||
SmallVectorImpl<Instruction*> &NewInsts) const {
|
||||
// See if we have a version of this value already available and dominating
|
||||
// PredBB. If so, there is no need to insert a new copy.
|
||||
if (Value *Res = GetAvailablePHITranslatedValue(InVal, CurBB, PredBB, TD, DT))
|
||||
return Res;
|
||||
|
||||
// If we don't have an available version of this value, it must be an
|
||||
// instruction.
|
||||
Instruction *Inst = cast<Instruction>(InVal);
|
||||
|
||||
// Handle bitcast of PHI translatable value.
|
||||
if (BitCastInst *BC = dyn_cast<BitCastInst>(Inst)) {
|
||||
Value *OpVal = InsertPHITranslatedPointer(BC->getOperand(0),
|
||||
CurBB, PredBB, TD, DT, NewInsts);
|
||||
if (OpVal == 0) return 0;
|
||||
|
||||
// Otherwise insert a bitcast at the end of PredBB.
|
||||
BitCastInst *New = new BitCastInst(OpVal, InVal->getType(),
|
||||
InVal->getName()+".phi.trans.insert",
|
||||
PredBB->getTerminator());
|
||||
NewInsts.push_back(New);
|
||||
return New;
|
||||
}
|
||||
|
||||
// Handle getelementptr with at least one PHI operand.
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
|
||||
SmallVector<Value*, 8> GEPOps;
|
||||
BasicBlock *CurBB = GEP->getParent();
|
||||
for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) {
|
||||
Value *OpVal = InsertPHITranslatedPointer(GEP->getOperand(i),
|
||||
CurBB, PredBB, TD, DT, NewInsts);
|
||||
if (OpVal == 0) return 0;
|
||||
GEPOps.push_back(OpVal);
|
||||
}
|
||||
|
||||
GetElementPtrInst *Result =
|
||||
GetElementPtrInst::Create(GEPOps[0], GEPOps.begin()+1, GEPOps.end(),
|
||||
InVal->getName()+".phi.trans.insert",
|
||||
PredBB->getTerminator());
|
||||
Result->setIsInBounds(GEP->isInBounds());
|
||||
NewInsts.push_back(Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// FIXME: This code works, but it is unclear that we actually want to insert
|
||||
// a big chain of computation in order to make a value available in a block.
|
||||
// This needs to be evaluated carefully to consider its cost trade offs.
|
||||
|
||||
// Handle add with a constant RHS.
|
||||
if (Inst->getOpcode() == Instruction::Add &&
|
||||
isa<ConstantInt>(Inst->getOperand(1))) {
|
||||
// PHI translate the LHS.
|
||||
Value *OpVal = InsertPHITranslatedPointer(Inst->getOperand(0),
|
||||
CurBB, PredBB, TD, DT, NewInsts);
|
||||
if (OpVal == 0) return 0;
|
||||
|
||||
BinaryOperator *Res = BinaryOperator::CreateAdd(OpVal, Inst->getOperand(1),
|
||||
InVal->getName()+".phi.trans.insert",
|
||||
PredBB->getTerminator());
|
||||
Res->setHasNoSignedWrap(cast<BinaryOperator>(Inst)->hasNoSignedWrap());
|
||||
Res->setHasNoUnsignedWrap(cast<BinaryOperator>(Inst)->hasNoUnsignedWrap());
|
||||
NewInsts.push_back(Res);
|
||||
return Res;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// getNonLocalPointerDepFromBB - Perform a dependency query based on
|
||||
/// pointer/pointeesize starting at the end of StartBB. Add any clobber/def
|
||||
/// results to the results vector and keep track of which blocks are visited in
|
||||
@ -989,14 +724,14 @@ InsertPHITranslatedPointer(Value *InVal, BasicBlock *CurBB,
|
||||
/// not compute dependence information for some reason. This should be treated
|
||||
/// as a clobber dependence on the first instruction in the predecessor block.
|
||||
bool MemoryDependenceAnalysis::
|
||||
getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
getNonLocalPointerDepFromBB(const PHITransAddr &Pointer, uint64_t PointeeSize,
|
||||
bool isLoad, BasicBlock *StartBB,
|
||||
SmallVectorImpl<NonLocalDepEntry> &Result,
|
||||
DenseMap<BasicBlock*, Value*> &Visited,
|
||||
bool SkipFirstBlock) {
|
||||
|
||||
// Look up the cached info for Pointer.
|
||||
ValueIsLoadPair CacheKey(Pointer, isLoad);
|
||||
ValueIsLoadPair CacheKey(Pointer.getAddr(), isLoad);
|
||||
|
||||
std::pair<BBSkipFirstBlockPair, NonLocalDepInfo> *CacheInfo =
|
||||
&NonLocalPointerDeps[CacheKey];
|
||||
@ -1013,8 +748,9 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
if (!Visited.empty()) {
|
||||
for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end();
|
||||
I != E; ++I) {
|
||||
DenseMap<BasicBlock*, Value*>::iterator VI = Visited.find(I->first);
|
||||
if (VI == Visited.end() || VI->second == Pointer) continue;
|
||||
DenseMap<BasicBlock*, Value*>::iterator VI = Visited.find(I->getBB());
|
||||
if (VI == Visited.end() || VI->second == Pointer.getAddr())
|
||||
continue;
|
||||
|
||||
// We have a pointer mismatch in a block. Just return clobber, saying
|
||||
// that something was clobbered in this result. We could also do a
|
||||
@ -1025,8 +761,8 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
|
||||
for (NonLocalDepInfo::iterator I = Cache->begin(), E = Cache->end();
|
||||
I != E; ++I) {
|
||||
Visited.insert(std::make_pair(I->first, Pointer));
|
||||
if (!I->second.isNonLocal())
|
||||
Visited.insert(std::make_pair(I->getBB(), Pointer.getAddr()));
|
||||
if (!I->getResult().isNonLocal())
|
||||
Result.push_back(*I);
|
||||
}
|
||||
++NumCacheCompleteNonLocalPtr;
|
||||
@ -1065,30 +801,27 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
// Get the dependency info for Pointer in BB. If we have cached
|
||||
// information, we will use it, otherwise we compute it.
|
||||
DEBUG(AssertSorted(*Cache, NumSortedEntries));
|
||||
MemDepResult Dep = GetNonLocalInfoForBlock(Pointer, PointeeSize, isLoad,
|
||||
BB, Cache, NumSortedEntries);
|
||||
MemDepResult Dep = GetNonLocalInfoForBlock(Pointer.getAddr(), PointeeSize,
|
||||
isLoad, BB, Cache,
|
||||
NumSortedEntries);
|
||||
|
||||
// If we got a Def or Clobber, add this to the list of results.
|
||||
if (!Dep.isNonLocal()) {
|
||||
Result.push_back(NonLocalDepEntry(BB, Dep));
|
||||
Result.push_back(NonLocalDepEntry(BB, Dep, Pointer.getAddr()));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If 'Pointer' is an instruction defined in this block, then we need to do
|
||||
// phi translation to change it into a value live in the predecessor block.
|
||||
// If phi translation fails, then we can't continue dependence analysis.
|
||||
Instruction *PtrInst = dyn_cast<Instruction>(Pointer);
|
||||
bool NeedsPHITranslation = PtrInst && PtrInst->getParent() == BB;
|
||||
|
||||
// If no PHI translation is needed, just add all the predecessors of this
|
||||
// block to scan them as well.
|
||||
if (!NeedsPHITranslation) {
|
||||
// If not, we just add the predecessors to the worklist and scan them with
|
||||
// the same Pointer.
|
||||
if (!Pointer.NeedsPHITranslationFromBlock(BB)) {
|
||||
SkipFirstBlock = false;
|
||||
for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) {
|
||||
// Verify that we haven't looked at this block yet.
|
||||
std::pair<DenseMap<BasicBlock*,Value*>::iterator, bool>
|
||||
InsertRes = Visited.insert(std::make_pair(*PI, Pointer));
|
||||
InsertRes = Visited.insert(std::make_pair(*PI, Pointer.getAddr()));
|
||||
if (InsertRes.second) {
|
||||
// First time we've looked at *PI.
|
||||
Worklist.push_back(*PI);
|
||||
@ -1098,16 +831,17 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
// If we have seen this block before, but it was with a different
|
||||
// pointer then we have a phi translation failure and we have to treat
|
||||
// this as a clobber.
|
||||
if (InsertRes.first->second != Pointer)
|
||||
if (InsertRes.first->second != Pointer.getAddr())
|
||||
goto PredTranslationFailure;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we do need to do phi translation, then there are a bunch of different
|
||||
// cases, because we have to find a Value* live in the predecessor block. We
|
||||
// know that PtrInst is defined in this block at least.
|
||||
|
||||
// We do need to do phi translation, if we know ahead of time we can't phi
|
||||
// translate this value, don't even try.
|
||||
if (!Pointer.IsPotentiallyPHITranslatable())
|
||||
goto PredTranslationFailure;
|
||||
|
||||
// We may have added values to the cache list before this PHI translation.
|
||||
// If so, we haven't done anything to ensure that the cache remains sorted.
|
||||
// Sort it now (if needed) so that recursive invocations of
|
||||
@ -1117,19 +851,17 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
SortNonLocalDepInfoCache(*Cache, NumSortedEntries);
|
||||
NumSortedEntries = Cache->size();
|
||||
}
|
||||
|
||||
// If this is a computation derived from a PHI node, use the suitably
|
||||
// translated incoming values for each pred as the phi translated version.
|
||||
if (!isPHITranslatable(PtrInst))
|
||||
goto PredTranslationFailure;
|
||||
|
||||
Cache = 0;
|
||||
|
||||
|
||||
for (BasicBlock **PI = PredCache->GetPreds(BB); *PI; ++PI) {
|
||||
BasicBlock *Pred = *PI;
|
||||
// Get the PHI translated pointer in this predecessor. This can fail and
|
||||
// return null if not translatable.
|
||||
Value *PredPtr = GetPHITranslatedValue(PtrInst, BB, Pred, TD);
|
||||
|
||||
// Get the PHI translated pointer in this predecessor. This can fail if
|
||||
// not translatable, in which case the getAddr() returns null.
|
||||
PHITransAddr PredPointer(Pointer);
|
||||
PredPointer.PHITranslateValue(BB, Pred);
|
||||
|
||||
Value *PredPtrVal = PredPointer.getAddr();
|
||||
|
||||
// Check to see if we have already visited this pred block with another
|
||||
// pointer. If so, we can't do this lookup. This failure can occur
|
||||
@ -1137,12 +869,12 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
// the successor translates to a pointer value different than the
|
||||
// pointer the block was first analyzed with.
|
||||
std::pair<DenseMap<BasicBlock*,Value*>::iterator, bool>
|
||||
InsertRes = Visited.insert(std::make_pair(Pred, PredPtr));
|
||||
InsertRes = Visited.insert(std::make_pair(Pred, PredPtrVal));
|
||||
|
||||
if (!InsertRes.second) {
|
||||
// If the predecessor was visited with PredPtr, then we already did
|
||||
// the analysis and can ignore it.
|
||||
if (InsertRes.first->second == PredPtr)
|
||||
if (InsertRes.first->second == PredPtrVal)
|
||||
continue;
|
||||
|
||||
// Otherwise, the block was previously analyzed with a different
|
||||
@ -1155,10 +887,11 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
// predecessor, then we have to assume that the pointer is clobbered in
|
||||
// that predecessor. We can still do PRE of the load, which would insert
|
||||
// a computation of the pointer in this predecessor.
|
||||
if (PredPtr == 0) {
|
||||
if (PredPtrVal == 0) {
|
||||
// Add the entry to the Result list.
|
||||
NonLocalDepEntry Entry(Pred,
|
||||
MemDepResult::getClobber(Pred->getTerminator()));
|
||||
MemDepResult::getClobber(Pred->getTerminator()),
|
||||
PredPtrVal);
|
||||
Result.push_back(Entry);
|
||||
|
||||
// Add it to the cache for this CacheKey so that subsequent queries get
|
||||
@ -1167,27 +900,27 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
MemoryDependenceAnalysis::NonLocalDepInfo::iterator It =
|
||||
std::upper_bound(Cache->begin(), Cache->end(), Entry);
|
||||
|
||||
if (It != Cache->begin() && prior(It)->first == Pred)
|
||||
if (It != Cache->begin() && (It-1)->getBB() == Pred)
|
||||
--It;
|
||||
|
||||
if (It == Cache->end() || It->first != Pred) {
|
||||
if (It == Cache->end() || It->getBB() != Pred) {
|
||||
Cache->insert(It, Entry);
|
||||
// Add it to the reverse map.
|
||||
ReverseNonLocalPtrDeps[Pred->getTerminator()].insert(CacheKey);
|
||||
} else if (!It->second.isDirty()) {
|
||||
} else if (!It->getResult().isDirty()) {
|
||||
// noop
|
||||
} else if (It->second.getInst() == Pred->getTerminator()) {
|
||||
} else if (It->getResult().getInst() == Pred->getTerminator()) {
|
||||
// Same instruction, clear the dirty marker.
|
||||
It->second = Entry.second;
|
||||
} else if (It->second.getInst() == 0) {
|
||||
It->setResult(Entry.getResult(), PredPtrVal);
|
||||
} else if (It->getResult().getInst() == 0) {
|
||||
// Dirty, with no instruction, just add this.
|
||||
It->second = Entry.second;
|
||||
It->setResult(Entry.getResult(), PredPtrVal);
|
||||
ReverseNonLocalPtrDeps[Pred->getTerminator()].insert(CacheKey);
|
||||
} else {
|
||||
// Otherwise, dirty with a different instruction.
|
||||
RemoveFromReverseMap(ReverseNonLocalPtrDeps, It->second.getInst(),
|
||||
CacheKey);
|
||||
It->second = Entry.second;
|
||||
RemoveFromReverseMap(ReverseNonLocalPtrDeps,
|
||||
It->getResult().getInst(), CacheKey);
|
||||
It->setResult(Entry.getResult(),PredPtrVal);
|
||||
ReverseNonLocalPtrDeps[Pred->getTerminator()].insert(CacheKey);
|
||||
}
|
||||
Cache = 0;
|
||||
@ -1201,7 +934,7 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
|
||||
// If we have a problem phi translating, fall through to the code below
|
||||
// to handle the failure condition.
|
||||
if (getNonLocalPointerDepFromBB(PredPtr, PointeeSize, isLoad, Pred,
|
||||
if (getNonLocalPointerDepFromBB(PredPointer, PointeeSize, isLoad, Pred,
|
||||
Result, Visited))
|
||||
goto PredTranslationFailure;
|
||||
}
|
||||
@ -1245,12 +978,12 @@ getNonLocalPointerDepFromBB(Value *Pointer, uint64_t PointeeSize,
|
||||
|
||||
for (NonLocalDepInfo::reverse_iterator I = Cache->rbegin(); ; ++I) {
|
||||
assert(I != Cache->rend() && "Didn't find current block??");
|
||||
if (I->first != BB)
|
||||
if (I->getBB() != BB)
|
||||
continue;
|
||||
|
||||
assert(I->second.isNonLocal() &&
|
||||
assert(I->getResult().isNonLocal() &&
|
||||
"Should only be here with transparent block");
|
||||
I->second = MemDepResult::getClobber(BB->begin());
|
||||
I->setResult(MemDepResult::getClobber(BB->begin()), Pointer.getAddr());
|
||||
ReverseNonLocalPtrDeps[BB->begin()].insert(CacheKey);
|
||||
Result.push_back(*I);
|
||||
break;
|
||||
@ -1276,9 +1009,9 @@ RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P) {
|
||||
NonLocalDepInfo &PInfo = It->second.second;
|
||||
|
||||
for (unsigned i = 0, e = PInfo.size(); i != e; ++i) {
|
||||
Instruction *Target = PInfo[i].second.getInst();
|
||||
Instruction *Target = PInfo[i].getResult().getInst();
|
||||
if (Target == 0) continue; // Ignore non-local dep results.
|
||||
assert(Target->getParent() == PInfo[i].first);
|
||||
assert(Target->getParent() == PInfo[i].getBB());
|
||||
|
||||
// Eliminating the dirty entry from 'Cache', so update the reverse info.
|
||||
RemoveFromReverseMap(ReverseNonLocalPtrDeps, Target, P);
|
||||
@ -1315,7 +1048,7 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
|
||||
NonLocalDepInfo &BlockMap = NLDI->second.first;
|
||||
for (NonLocalDepInfo::iterator DI = BlockMap.begin(), DE = BlockMap.end();
|
||||
DI != DE; ++DI)
|
||||
if (Instruction *Inst = DI->second.getInst())
|
||||
if (Instruction *Inst = DI->getResult().getInst())
|
||||
RemoveFromReverseMap(ReverseNonLocalDeps, Inst, RemInst);
|
||||
NonLocalDeps.erase(NLDI);
|
||||
}
|
||||
@ -1403,10 +1136,10 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
|
||||
|
||||
for (NonLocalDepInfo::iterator DI = INLD.first.begin(),
|
||||
DE = INLD.first.end(); DI != DE; ++DI) {
|
||||
if (DI->second.getInst() != RemInst) continue;
|
||||
if (DI->getResult().getInst() != RemInst) continue;
|
||||
|
||||
// Convert to a dirty entry for the subsequent instruction.
|
||||
DI->second = NewDirtyVal;
|
||||
DI->setResult(NewDirtyVal, DI->getAddress());
|
||||
|
||||
if (Instruction *NextI = NewDirtyVal.getInst())
|
||||
ReverseDepsToAdd.push_back(std::make_pair(NextI, *I));
|
||||
@ -1445,10 +1178,10 @@ void MemoryDependenceAnalysis::removeInstruction(Instruction *RemInst) {
|
||||
// Update any entries for RemInst to use the instruction after it.
|
||||
for (NonLocalDepInfo::iterator DI = NLPDI.begin(), DE = NLPDI.end();
|
||||
DI != DE; ++DI) {
|
||||
if (DI->second.getInst() != RemInst) continue;
|
||||
if (DI->getResult().getInst() != RemInst) continue;
|
||||
|
||||
// Convert to a dirty entry for the subsequent instruction.
|
||||
DI->second = NewDirtyVal;
|
||||
DI->setResult(NewDirtyVal, DI->getAddress());
|
||||
|
||||
if (Instruction *NewDirtyInst = NewDirtyVal.getInst())
|
||||
ReversePtrDepsToAdd.push_back(std::make_pair(NewDirtyInst, P));
|
||||
@ -1489,7 +1222,7 @@ void MemoryDependenceAnalysis::verifyRemoved(Instruction *D) const {
|
||||
const NonLocalDepInfo &Val = I->second.second;
|
||||
for (NonLocalDepInfo::const_iterator II = Val.begin(), E = Val.end();
|
||||
II != E; ++II)
|
||||
assert(II->second.getInst() != D && "Inst occurs as NLPD value");
|
||||
assert(II->getResult().getInst() != D && "Inst occurs as NLPD value");
|
||||
}
|
||||
|
||||
for (NonLocalDepMapType::const_iterator I = NonLocalDeps.begin(),
|
||||
@ -1498,7 +1231,7 @@ void MemoryDependenceAnalysis::verifyRemoved(Instruction *D) const {
|
||||
const PerInstNLInfo &INLD = I->second;
|
||||
for (NonLocalDepInfo::const_iterator II = INLD.first.begin(),
|
||||
EE = INLD.first.end(); II != EE; ++II)
|
||||
assert(II->second.getInst() != D && "Inst occurs in data structures");
|
||||
assert(II->getResult().getInst() != D && "Inst occurs in data structures");
|
||||
}
|
||||
|
||||
for (ReverseDepMapType::const_iterator I = ReverseLocalDeps.begin(),
|
||||
|
432
lib/Analysis/PHITransAddr.cpp
Normal file
432
lib/Analysis/PHITransAddr.cpp
Normal file
@ -0,0 +1,432 @@
|
||||
//===- PHITransAddr.cpp - PHI Translation for Addresses -------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the PHITransAddr class.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/PHITransAddr.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
static bool CanPHITrans(Instruction *Inst) {
|
||||
if (isa<PHINode>(Inst) ||
|
||||
isa<BitCastInst>(Inst) ||
|
||||
isa<GetElementPtrInst>(Inst))
|
||||
return true;
|
||||
|
||||
if (Inst->getOpcode() == Instruction::Add &&
|
||||
isa<ConstantInt>(Inst->getOperand(1)))
|
||||
return true;
|
||||
|
||||
// cerr << "MEMDEP: Could not PHI translate: " << *Pointer;
|
||||
// if (isa<BitCastInst>(PtrInst) || isa<GetElementPtrInst>(PtrInst))
|
||||
// cerr << "OP:\t\t\t\t" << *PtrInst->getOperand(0);
|
||||
return false;
|
||||
}
|
||||
|
||||
void PHITransAddr::dump() const {
|
||||
if (Addr == 0) {
|
||||
errs() << "PHITransAddr: null\n";
|
||||
return;
|
||||
}
|
||||
errs() << "PHITransAddr: " << *Addr << "\n";
|
||||
for (unsigned i = 0, e = InstInputs.size(); i != e; ++i)
|
||||
errs() << " Input #" << i << " is " << *InstInputs[i] << "\n";
|
||||
}
|
||||
|
||||
|
||||
static bool VerifySubExpr(Value *Expr,
|
||||
SmallVectorImpl<Instruction*> &InstInputs) {
|
||||
// If this is a non-instruction value, there is nothing to do.
|
||||
Instruction *I = dyn_cast<Instruction>(Expr);
|
||||
if (I == 0) return true;
|
||||
|
||||
// If it's an instruction, it is either in Tmp or its operands recursively
|
||||
// are.
|
||||
SmallVectorImpl<Instruction*>::iterator Entry =
|
||||
std::find(InstInputs.begin(), InstInputs.end(), I);
|
||||
if (Entry != InstInputs.end()) {
|
||||
InstInputs.erase(Entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If it isn't in the InstInputs list it is a subexpr incorporated into the
|
||||
// address. Sanity check that it is phi translatable.
|
||||
if (!CanPHITrans(I)) {
|
||||
errs() << "Non phi translatable instruction found in PHITransAddr, either "
|
||||
"something is missing from InstInputs or CanPHITrans is wrong:\n";
|
||||
errs() << *I << '\n';
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the operands of the instruction.
|
||||
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
|
||||
if (!VerifySubExpr(I->getOperand(i), InstInputs))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Verify - Check internal consistency of this data structure. If the
|
||||
/// structure is valid, it returns true. If invalid, it prints errors and
|
||||
/// returns false.
|
||||
bool PHITransAddr::Verify() const {
|
||||
if (Addr == 0) return true;
|
||||
|
||||
SmallVector<Instruction*, 8> Tmp(InstInputs.begin(), InstInputs.end());
|
||||
|
||||
if (!VerifySubExpr(Addr, Tmp))
|
||||
return false;
|
||||
|
||||
if (!Tmp.empty()) {
|
||||
errs() << "PHITransAddr inconsistent, contains extra instructions:\n";
|
||||
for (unsigned i = 0, e = InstInputs.size(); i != e; ++i)
|
||||
errs() << " InstInput #" << i << " is " << *InstInputs[i] << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// a-ok.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/// IsPotentiallyPHITranslatable - If this needs PHI translation, return true
|
||||
/// if we have some hope of doing it. This should be used as a filter to
|
||||
/// avoid calling PHITranslateValue in hopeless situations.
|
||||
bool PHITransAddr::IsPotentiallyPHITranslatable() const {
|
||||
// If the input value is not an instruction, or if it is not defined in CurBB,
|
||||
// then we don't need to phi translate it.
|
||||
Instruction *Inst = dyn_cast<Instruction>(Addr);
|
||||
return Inst == 0 || CanPHITrans(Inst);
|
||||
}
|
||||
|
||||
|
||||
static void RemoveInstInputs(Value *V,
|
||||
SmallVectorImpl<Instruction*> &InstInputs) {
|
||||
Instruction *I = dyn_cast<Instruction>(V);
|
||||
if (I == 0) return;
|
||||
|
||||
// If the instruction is in the InstInputs list, remove it.
|
||||
SmallVectorImpl<Instruction*>::iterator Entry =
|
||||
std::find(InstInputs.begin(), InstInputs.end(), I);
|
||||
if (Entry != InstInputs.end()) {
|
||||
InstInputs.erase(Entry);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!isa<PHINode>(I) && "Error, removing something that isn't an input");
|
||||
|
||||
// Otherwise, it must have instruction inputs itself. Zap them recursively.
|
||||
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
|
||||
if (Instruction *Op = dyn_cast<Instruction>(I->getOperand(i)))
|
||||
RemoveInstInputs(Op, InstInputs);
|
||||
}
|
||||
}
|
||||
|
||||
Value *PHITransAddr::PHITranslateSubExpr(Value *V, BasicBlock *CurBB,
|
||||
BasicBlock *PredBB) {
|
||||
// If this is a non-instruction value, it can't require PHI translation.
|
||||
Instruction *Inst = dyn_cast<Instruction>(V);
|
||||
if (Inst == 0) return V;
|
||||
|
||||
// Determine whether 'Inst' is an input to our PHI translatable expression.
|
||||
bool isInput = std::count(InstInputs.begin(), InstInputs.end(), Inst);
|
||||
|
||||
// Handle inputs instructions if needed.
|
||||
if (isInput) {
|
||||
if (Inst->getParent() != CurBB) {
|
||||
// If it is an input defined in a different block, then it remains an
|
||||
// input.
|
||||
return Inst;
|
||||
}
|
||||
|
||||
// If 'Inst' is defined in this block and is an input that needs to be phi
|
||||
// translated, we need to incorporate the value into the expression or fail.
|
||||
|
||||
// In either case, the instruction itself isn't an input any longer.
|
||||
InstInputs.erase(std::find(InstInputs.begin(), InstInputs.end(), Inst));
|
||||
|
||||
// If this is a PHI, go ahead and translate it.
|
||||
if (PHINode *PN = dyn_cast<PHINode>(Inst))
|
||||
return AddAsInput(PN->getIncomingValueForBlock(PredBB));
|
||||
|
||||
// If this is a non-phi value, and it is analyzable, we can incorporate it
|
||||
// into the expression by making all instruction operands be inputs.
|
||||
if (!CanPHITrans(Inst))
|
||||
return 0;
|
||||
|
||||
// All instruction operands are now inputs (and of course, they may also be
|
||||
// defined in this block, so they may need to be phi translated themselves.
|
||||
for (unsigned i = 0, e = Inst->getNumOperands(); i != e; ++i)
|
||||
if (Instruction *Op = dyn_cast<Instruction>(Inst->getOperand(i)))
|
||||
InstInputs.push_back(Op);
|
||||
}
|
||||
|
||||
// Ok, it must be an intermediate result (either because it started that way
|
||||
// or because we just incorporated it into the expression). See if its
|
||||
// operands need to be phi translated, and if so, reconstruct it.
|
||||
|
||||
if (BitCastInst *BC = dyn_cast<BitCastInst>(Inst)) {
|
||||
Value *PHIIn = PHITranslateSubExpr(BC->getOperand(0), CurBB, PredBB);
|
||||
if (PHIIn == 0) return 0;
|
||||
if (PHIIn == BC->getOperand(0))
|
||||
return BC;
|
||||
|
||||
// Find an available version of this cast.
|
||||
|
||||
// Constants are trivial to find.
|
||||
if (Constant *C = dyn_cast<Constant>(PHIIn))
|
||||
return AddAsInput(ConstantExpr::getBitCast(C, BC->getType()));
|
||||
|
||||
// Otherwise we have to see if a bitcasted version of the incoming pointer
|
||||
// is available. If so, we can use it, otherwise we have to fail.
|
||||
for (Value::use_iterator UI = PHIIn->use_begin(), E = PHIIn->use_end();
|
||||
UI != E; ++UI) {
|
||||
if (BitCastInst *BCI = dyn_cast<BitCastInst>(*UI))
|
||||
if (BCI->getType() == BC->getType())
|
||||
return BCI;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle getelementptr with at least one PHI translatable operand.
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
|
||||
SmallVector<Value*, 8> GEPOps;
|
||||
bool AnyChanged = false;
|
||||
for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) {
|
||||
Value *GEPOp = PHITranslateSubExpr(GEP->getOperand(i), CurBB, PredBB);
|
||||
if (GEPOp == 0) return 0;
|
||||
|
||||
AnyChanged |= GEPOp != GEP->getOperand(i);
|
||||
GEPOps.push_back(GEPOp);
|
||||
}
|
||||
|
||||
if (!AnyChanged)
|
||||
return GEP;
|
||||
|
||||
// Simplify the GEP to handle 'gep x, 0' -> x etc.
|
||||
if (Value *V = SimplifyGEPInst(&GEPOps[0], GEPOps.size(), TD)) {
|
||||
for (unsigned i = 0, e = GEPOps.size(); i != e; ++i)
|
||||
RemoveInstInputs(GEPOps[i], InstInputs);
|
||||
|
||||
return AddAsInput(V);
|
||||
}
|
||||
|
||||
// Scan to see if we have this GEP available.
|
||||
Value *APHIOp = GEPOps[0];
|
||||
for (Value::use_iterator UI = APHIOp->use_begin(), E = APHIOp->use_end();
|
||||
UI != E; ++UI) {
|
||||
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*UI))
|
||||
if (GEPI->getType() == GEP->getType() &&
|
||||
GEPI->getNumOperands() == GEPOps.size() &&
|
||||
GEPI->getParent()->getParent() == CurBB->getParent()) {
|
||||
bool Mismatch = false;
|
||||
for (unsigned i = 0, e = GEPOps.size(); i != e; ++i)
|
||||
if (GEPI->getOperand(i) != GEPOps[i]) {
|
||||
Mismatch = true;
|
||||
break;
|
||||
}
|
||||
if (!Mismatch)
|
||||
return GEPI;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle add with a constant RHS.
|
||||
if (Inst->getOpcode() == Instruction::Add &&
|
||||
isa<ConstantInt>(Inst->getOperand(1))) {
|
||||
// PHI translate the LHS.
|
||||
Constant *RHS = cast<ConstantInt>(Inst->getOperand(1));
|
||||
bool isNSW = cast<BinaryOperator>(Inst)->hasNoSignedWrap();
|
||||
bool isNUW = cast<BinaryOperator>(Inst)->hasNoUnsignedWrap();
|
||||
|
||||
Value *LHS = PHITranslateSubExpr(Inst->getOperand(0), CurBB, PredBB);
|
||||
if (LHS == 0) return 0;
|
||||
|
||||
// If the PHI translated LHS is an add of a constant, fold the immediates.
|
||||
if (BinaryOperator *BOp = dyn_cast<BinaryOperator>(LHS))
|
||||
if (BOp->getOpcode() == Instruction::Add)
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(BOp->getOperand(1))) {
|
||||
LHS = BOp->getOperand(0);
|
||||
RHS = ConstantExpr::getAdd(RHS, CI);
|
||||
isNSW = isNUW = false;
|
||||
|
||||
// If the old 'LHS' was an input, add the new 'LHS' as an input.
|
||||
if (std::count(InstInputs.begin(), InstInputs.end(), BOp)) {
|
||||
RemoveInstInputs(BOp, InstInputs);
|
||||
AddAsInput(LHS);
|
||||
}
|
||||
}
|
||||
|
||||
// See if the add simplifies away.
|
||||
if (Value *Res = SimplifyAddInst(LHS, RHS, isNSW, isNUW, TD)) {
|
||||
// If we simplified the operands, the LHS is no longer an input, but Res
|
||||
// is.
|
||||
RemoveInstInputs(LHS, InstInputs);
|
||||
return AddAsInput(Res);
|
||||
}
|
||||
|
||||
// If we didn't modify the add, just return it.
|
||||
if (LHS == Inst->getOperand(0) && RHS == Inst->getOperand(1))
|
||||
return Inst;
|
||||
|
||||
// Otherwise, see if we have this add available somewhere.
|
||||
for (Value::use_iterator UI = LHS->use_begin(), E = LHS->use_end();
|
||||
UI != E; ++UI) {
|
||||
if (BinaryOperator *BO = dyn_cast<BinaryOperator>(*UI))
|
||||
if (BO->getOpcode() == Instruction::Add &&
|
||||
BO->getOperand(0) == LHS && BO->getOperand(1) == RHS &&
|
||||
BO->getParent()->getParent() == CurBB->getParent())
|
||||
return BO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Otherwise, we failed.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// PHITranslateValue - PHI translate the current address up the CFG from
|
||||
/// CurBB to Pred, updating our state the reflect any needed changes. This
|
||||
/// returns true on failure and sets Addr to null.
|
||||
bool PHITransAddr::PHITranslateValue(BasicBlock *CurBB, BasicBlock *PredBB) {
|
||||
assert(Verify() && "Invalid PHITransAddr!");
|
||||
Addr = PHITranslateSubExpr(Addr, CurBB, PredBB);
|
||||
assert(Verify() && "Invalid PHITransAddr!");
|
||||
return Addr == 0;
|
||||
}
|
||||
|
||||
/// GetAvailablePHITranslatedSubExpr - Return the value computed by
|
||||
/// PHITranslateSubExpr if it dominates PredBB, otherwise return null.
|
||||
Value *PHITransAddr::
|
||||
GetAvailablePHITranslatedSubExpr(Value *V, BasicBlock *CurBB,BasicBlock *PredBB,
|
||||
const DominatorTree &DT) const {
|
||||
PHITransAddr Tmp(V, TD);
|
||||
Tmp.PHITranslateValue(CurBB, PredBB);
|
||||
|
||||
// See if PHI translation succeeds.
|
||||
V = Tmp.getAddr();
|
||||
|
||||
// Make sure the value is live in the predecessor.
|
||||
if (Instruction *Inst = dyn_cast_or_null<Instruction>(V))
|
||||
if (!DT.dominates(Inst->getParent(), PredBB))
|
||||
return 0;
|
||||
return V;
|
||||
}
|
||||
|
||||
|
||||
/// PHITranslateWithInsertion - PHI translate this value into the specified
|
||||
/// predecessor block, inserting a computation of the value if it is
|
||||
/// unavailable.
|
||||
///
|
||||
/// All newly created instructions are added to the NewInsts list. This
|
||||
/// returns null on failure.
|
||||
///
|
||||
Value *PHITransAddr::
|
||||
PHITranslateWithInsertion(BasicBlock *CurBB, BasicBlock *PredBB,
|
||||
const DominatorTree &DT,
|
||||
SmallVectorImpl<Instruction*> &NewInsts) {
|
||||
unsigned NISize = NewInsts.size();
|
||||
|
||||
// Attempt to PHI translate with insertion.
|
||||
Addr = InsertPHITranslatedSubExpr(Addr, CurBB, PredBB, DT, NewInsts);
|
||||
|
||||
// If successful, return the new value.
|
||||
if (Addr) return Addr;
|
||||
|
||||
// If not, destroy any intermediate instructions inserted.
|
||||
while (NewInsts.size() != NISize)
|
||||
NewInsts.pop_back_val()->eraseFromParent();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// InsertPHITranslatedPointer - Insert a computation of the PHI translated
|
||||
/// version of 'V' for the edge PredBB->CurBB into the end of the PredBB
|
||||
/// block. All newly created instructions are added to the NewInsts list.
|
||||
/// This returns null on failure.
|
||||
///
|
||||
Value *PHITransAddr::
|
||||
InsertPHITranslatedSubExpr(Value *InVal, BasicBlock *CurBB,
|
||||
BasicBlock *PredBB, const DominatorTree &DT,
|
||||
SmallVectorImpl<Instruction*> &NewInsts) {
|
||||
// See if we have a version of this value already available and dominating
|
||||
// PredBB. If so, there is no need to insert a new instance of it.
|
||||
if (Value *Res = GetAvailablePHITranslatedSubExpr(InVal, CurBB, PredBB, DT))
|
||||
return Res;
|
||||
|
||||
// If we don't have an available version of this value, it must be an
|
||||
// instruction.
|
||||
Instruction *Inst = cast<Instruction>(InVal);
|
||||
|
||||
// Handle bitcast of PHI translatable value.
|
||||
if (BitCastInst *BC = dyn_cast<BitCastInst>(Inst)) {
|
||||
Value *OpVal = InsertPHITranslatedSubExpr(BC->getOperand(0),
|
||||
CurBB, PredBB, DT, NewInsts);
|
||||
if (OpVal == 0) return 0;
|
||||
|
||||
// Otherwise insert a bitcast at the end of PredBB.
|
||||
BitCastInst *New = new BitCastInst(OpVal, InVal->getType(),
|
||||
InVal->getName()+".phi.trans.insert",
|
||||
PredBB->getTerminator());
|
||||
NewInsts.push_back(New);
|
||||
return New;
|
||||
}
|
||||
|
||||
// Handle getelementptr with at least one PHI operand.
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(Inst)) {
|
||||
SmallVector<Value*, 8> GEPOps;
|
||||
BasicBlock *CurBB = GEP->getParent();
|
||||
for (unsigned i = 0, e = GEP->getNumOperands(); i != e; ++i) {
|
||||
Value *OpVal = InsertPHITranslatedSubExpr(GEP->getOperand(i),
|
||||
CurBB, PredBB, DT, NewInsts);
|
||||
if (OpVal == 0) return 0;
|
||||
GEPOps.push_back(OpVal);
|
||||
}
|
||||
|
||||
GetElementPtrInst *Result =
|
||||
GetElementPtrInst::Create(GEPOps[0], GEPOps.begin()+1, GEPOps.end(),
|
||||
InVal->getName()+".phi.trans.insert",
|
||||
PredBB->getTerminator());
|
||||
Result->setIsInBounds(GEP->isInBounds());
|
||||
NewInsts.push_back(Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// FIXME: This code works, but it is unclear that we actually want to insert
|
||||
// a big chain of computation in order to make a value available in a block.
|
||||
// This needs to be evaluated carefully to consider its cost trade offs.
|
||||
|
||||
// Handle add with a constant RHS.
|
||||
if (Inst->getOpcode() == Instruction::Add &&
|
||||
isa<ConstantInt>(Inst->getOperand(1))) {
|
||||
// PHI translate the LHS.
|
||||
Value *OpVal = InsertPHITranslatedSubExpr(Inst->getOperand(0),
|
||||
CurBB, PredBB, DT, NewInsts);
|
||||
if (OpVal == 0) return 0;
|
||||
|
||||
BinaryOperator *Res = BinaryOperator::CreateAdd(OpVal, Inst->getOperand(1),
|
||||
InVal->getName()+".phi.trans.insert",
|
||||
PredBB->getTerminator());
|
||||
Res->setHasNoSignedWrap(cast<BinaryOperator>(Inst)->hasNoSignedWrap());
|
||||
Res->setHasNoUnsignedWrap(cast<BinaryOperator>(Inst)->hasNoUnsignedWrap());
|
||||
NewInsts.push_back(Res);
|
||||
return Res;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
@ -35,6 +35,7 @@ namespace {
|
||||
LoopInfo *LI;
|
||||
std::set<BasicBlock*> BBToVisit;
|
||||
std::map<Loop*,double> LoopExitWeights;
|
||||
std::map<Edge,double> MinimalWeight;
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
explicit ProfileEstimatorPass(const double execcount = 0)
|
||||
@ -91,7 +92,7 @@ static void inline printEdgeError(ProfileInfo::Edge e, const char *M) {
|
||||
|
||||
void inline ProfileEstimatorPass::printEdgeWeight(Edge E) {
|
||||
DEBUG(errs() << "-- Weight of Edge " << E << ":"
|
||||
<< format("%g", getEdgeWeight(E)) << "\n");
|
||||
<< format("%20.20g", getEdgeWeight(E)) << "\n");
|
||||
}
|
||||
|
||||
// recurseBasicBlock() - This calculates the ProfileInfo estimation for a
|
||||
@ -174,6 +175,12 @@ void ProfileEstimatorPass::recurseBasicBlock(BasicBlock *BB) {
|
||||
double w = getEdgeWeight(*ei);
|
||||
if (w == MissingValue) {
|
||||
Edges.push_back(*ei);
|
||||
// Check if there is a necessary minimal weight, if yes, subtract it
|
||||
// from weight.
|
||||
if (MinimalWeight.find(*ei) != MinimalWeight.end()) {
|
||||
incoming -= MinimalWeight[*ei];
|
||||
DEBUG(errs() << "Reserving " << format("%.20g",MinimalWeight[*ei]) << " at " << (*ei) << "\n");
|
||||
}
|
||||
} else {
|
||||
incoming -= w;
|
||||
}
|
||||
@ -191,11 +198,43 @@ void ProfileEstimatorPass::recurseBasicBlock(BasicBlock *BB) {
|
||||
printEdgeWeight(edge);
|
||||
}
|
||||
}
|
||||
// Distribute remaining weight onto the exit edges.
|
||||
|
||||
// Distribute remaining weight to the exting edges. To prevent fractions
|
||||
// from building up and provoking precision problems the weight which is to
|
||||
// be distributed is split and the rounded, the last edge gets a somewhat
|
||||
// bigger value, but we are close enough for an estimation.
|
||||
double fraction = floor(incoming/Edges.size());
|
||||
for (SmallVector<Edge, 8>::iterator ei = Edges.begin(), ee = Edges.end();
|
||||
ei != ee; ++ei) {
|
||||
EdgeInformation[BB->getParent()][*ei] += incoming/Edges.size();
|
||||
double w = 0;
|
||||
if (ei != (ee-1)) {
|
||||
w = fraction;
|
||||
incoming -= fraction;
|
||||
} else {
|
||||
w = incoming;
|
||||
}
|
||||
EdgeInformation[BB->getParent()][*ei] += w;
|
||||
// Read necessary minimal weight.
|
||||
if (MinimalWeight.find(*ei) != MinimalWeight.end()) {
|
||||
EdgeInformation[BB->getParent()][*ei] += MinimalWeight[*ei];
|
||||
DEBUG(errs() << "Additionally " << format("%.20g",MinimalWeight[*ei]) << " at " << (*ei) << "\n");
|
||||
}
|
||||
printEdgeWeight(*ei);
|
||||
|
||||
// Add minimal weight to paths to all exit edges, this is used to ensure
|
||||
// that enough flow is reaching this edges.
|
||||
Path p;
|
||||
const BasicBlock *Dest = GetPath(BB, (*ei).first, p, GetPathToDest);
|
||||
while (Dest != BB) {
|
||||
const BasicBlock *Parent = p.find(Dest)->second;
|
||||
Edge e = getEdge(Parent, Dest);
|
||||
if (MinimalWeight.find(e) == MinimalWeight.end()) {
|
||||
MinimalWeight[e] = 0;
|
||||
}
|
||||
MinimalWeight[e] += w;
|
||||
DEBUG(errs() << "Minimal Weight for " << e << ": " << format("%.20g",MinimalWeight[e]) << "\n");
|
||||
Dest = Parent;
|
||||
}
|
||||
}
|
||||
// Increase flow into the loop.
|
||||
BBWeight *= (ExecCount+1);
|
||||
@ -203,7 +242,7 @@ void ProfileEstimatorPass::recurseBasicBlock(BasicBlock *BB) {
|
||||
|
||||
BlockInformation[BB->getParent()][BB] = BBWeight;
|
||||
// Up until now we considered only the loop exiting edges, now we have a
|
||||
// definite block weight and must ditribute this onto the outgoing edges.
|
||||
// definite block weight and must distribute this onto the outgoing edges.
|
||||
// Since there may be already flow attached to some of the edges, read this
|
||||
// flow first and remember the edges that have still now flow attached.
|
||||
Edges.clear();
|
||||
@ -225,15 +264,32 @@ void ProfileEstimatorPass::recurseBasicBlock(BasicBlock *BB) {
|
||||
BBWeight -= getEdgeWeight(edge);
|
||||
} else {
|
||||
Edges.push_back(edge);
|
||||
// If minimal weight is necessary, reserve weight by subtracting weight
|
||||
// from block weight, this is readded later on.
|
||||
if (MinimalWeight.find(edge) != MinimalWeight.end()) {
|
||||
BBWeight -= MinimalWeight[edge];
|
||||
DEBUG(errs() << "Reserving " << format("%.20g",MinimalWeight[edge]) << " at " << edge << "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double fraction = floor(BBWeight/Edges.size());
|
||||
// Finally we know what flow is still not leaving the block, distribute this
|
||||
// flow onto the empty edges.
|
||||
for (SmallVector<Edge, 8>::iterator ei = Edges.begin(), ee = Edges.end();
|
||||
ei != ee; ++ei) {
|
||||
EdgeInformation[BB->getParent()][*ei] += BBWeight/Edges.size();
|
||||
if (ei != (ee-1)) {
|
||||
EdgeInformation[BB->getParent()][*ei] += fraction;
|
||||
BBWeight -= fraction;
|
||||
} else {
|
||||
EdgeInformation[BB->getParent()][*ei] += BBWeight;
|
||||
}
|
||||
// Readd minial necessary weight.
|
||||
if (MinimalWeight.find(*ei) != MinimalWeight.end()) {
|
||||
EdgeInformation[BB->getParent()][*ei] += MinimalWeight[*ei];
|
||||
DEBUG(errs() << "Additionally " << format("%.20g",MinimalWeight[*ei]) << " at " << (*ei) << "\n");
|
||||
}
|
||||
printEdgeWeight(*ei);
|
||||
}
|
||||
|
||||
@ -260,20 +316,24 @@ bool ProfileEstimatorPass::runOnFunction(Function &F) {
|
||||
for (Function::iterator bi = F.begin(), be = F.end(); bi != be; ++bi)
|
||||
BBToVisit.insert(bi);
|
||||
|
||||
// Clear Minimal Edges.
|
||||
MinimalWeight.clear();
|
||||
|
||||
DEBUG(errs() << "Working on function " << F.getNameStr() << "\n");
|
||||
|
||||
// Since the entry block is the first one and has no predecessors, the edge
|
||||
// (0,entry) is inserted with the starting weight of 1.
|
||||
BasicBlock *entry = &F.getEntryBlock();
|
||||
BlockInformation[&F][entry] = 1;
|
||||
BlockInformation[&F][entry] = pow(2.0, 32.0);
|
||||
Edge edge = getEdge(0,entry);
|
||||
EdgeInformation[&F][edge] = 1;
|
||||
EdgeInformation[&F][edge] = BlockInformation[&F][entry];
|
||||
printEdgeWeight(edge);
|
||||
|
||||
// Since recurseBasicBlock() maybe returns with a block which was not fully
|
||||
// estimated, use recurseBasicBlock() until everything is calculated.
|
||||
// estimated, use recurseBasicBlock() until everything is calculated.
|
||||
bool cleanup = false;
|
||||
recurseBasicBlock(entry);
|
||||
while (BBToVisit.size() > 0) {
|
||||
while (BBToVisit.size() > 0 && !cleanup) {
|
||||
// Remember number of open blocks, this is later used to check if progress
|
||||
// was made.
|
||||
unsigned size = BBToVisit.size();
|
||||
@ -287,21 +347,65 @@ bool ProfileEstimatorPass::runOnFunction(Function &F) {
|
||||
if (BBToVisit.size() < size) break;
|
||||
}
|
||||
|
||||
// If there was not a single block resovled, make some assumptions.
|
||||
// If there was not a single block resolved, make some assumptions.
|
||||
if (BBToVisit.size() == size) {
|
||||
BasicBlock *BB = *(BBToVisit.begin());
|
||||
// Since this BB was not calculated because of missing incoming edges,
|
||||
// set these edges to zero.
|
||||
for (pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
bbi != bbe; ++bbi) {
|
||||
Edge e = getEdge(*bbi,BB);
|
||||
double w = getEdgeWeight(e);
|
||||
if (w == MissingValue) {
|
||||
EdgeInformation[&F][e] = 0;
|
||||
DEBUG(errs() << "Assuming edge weight: ");
|
||||
printEdgeWeight(e);
|
||||
bool found = false;
|
||||
for (std::set<BasicBlock*>::iterator BBI = BBToVisit.begin(), BBE = BBToVisit.end();
|
||||
(BBI != BBE) && (!found); ++BBI) {
|
||||
BasicBlock *BB = *BBI;
|
||||
// Try each predecessor if it can be assumend.
|
||||
for (pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
(bbi != bbe) && (!found); ++bbi) {
|
||||
Edge e = getEdge(*bbi,BB);
|
||||
double w = getEdgeWeight(e);
|
||||
// Check that edge from predecessor is still free.
|
||||
if (w == MissingValue) {
|
||||
// Check if there is a circle from this block to predecessor.
|
||||
Path P;
|
||||
const BasicBlock *Dest = GetPath(BB, *bbi, P, GetPathToDest);
|
||||
if (Dest != *bbi) {
|
||||
// If there is no circle, just set edge weight to 0
|
||||
EdgeInformation[&F][e] = 0;
|
||||
DEBUG(errs() << "Assuming edge weight: ");
|
||||
printEdgeWeight(e);
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
cleanup = true;
|
||||
DEBUG(errs() << "No assumption possible in Fuction "<<F.getName()<<", setting all to zero\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
// In case there was no safe way to assume edges, set as a last measure,
|
||||
// set _everything_ to zero.
|
||||
if (cleanup) {
|
||||
FunctionInformation[&F] = 0;
|
||||
BlockInformation[&F].clear();
|
||||
EdgeInformation[&F].clear();
|
||||
for (Function::const_iterator FI = F.begin(), FE = F.end(); FI != FE; ++FI) {
|
||||
const BasicBlock *BB = &(*FI);
|
||||
BlockInformation[&F][BB] = 0;
|
||||
pred_const_iterator predi = pred_begin(BB), prede = pred_end(BB);
|
||||
if (predi == prede) {
|
||||
Edge e = getEdge(0,BB);
|
||||
setEdgeWeight(e,0);
|
||||
}
|
||||
for (;predi != prede; ++predi) {
|
||||
Edge e = getEdge(*predi,BB);
|
||||
setEdgeWeight(e,0);
|
||||
}
|
||||
succ_const_iterator succi = succ_begin(BB), succe = succ_end(BB);
|
||||
if (succi == succe) {
|
||||
Edge e = getEdge(BB,0);
|
||||
setEdgeWeight(e,0);
|
||||
}
|
||||
for (;succi != succe; ++succi) {
|
||||
Edge e = getEdge(*succi,BB);
|
||||
setEdgeWeight(e,0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -74,6 +74,8 @@ X("profile-loader", "Load profile information from llvmprof.out", false, true);
|
||||
|
||||
static RegisterAnalysisGroup<ProfileInfo> Y(X);
|
||||
|
||||
const PassInfo *llvm::ProfileLoaderPassID = &X;
|
||||
|
||||
ModulePass *llvm::createProfileLoaderPass() { return new LoaderPass(); }
|
||||
|
||||
/// createProfileLoaderPass - This function returns a Pass that loads the
|
||||
@ -112,46 +114,9 @@ void LoaderPass::recurseBasicBlock(const BasicBlock *BB) {
|
||||
recurseBasicBlock(*bbi);
|
||||
}
|
||||
|
||||
Edge edgetocalc;
|
||||
unsigned uncalculated = 0;
|
||||
|
||||
// collect weights of all incoming and outgoing edges, rememer edges that
|
||||
// have no value
|
||||
double incount = 0;
|
||||
SmallSet<const BasicBlock*,8> pred_visited;
|
||||
pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
if (bbi==bbe) {
|
||||
readEdgeOrRemember(getEdge(0, BB),edgetocalc,uncalculated,incount);
|
||||
}
|
||||
for (;bbi != bbe; ++bbi) {
|
||||
if (pred_visited.insert(*bbi)) {
|
||||
readEdgeOrRemember(getEdge(*bbi, BB),edgetocalc,uncalculated,incount);
|
||||
}
|
||||
}
|
||||
|
||||
double outcount = 0;
|
||||
SmallSet<const BasicBlock*,8> succ_visited;
|
||||
succ_const_iterator sbbi = succ_begin(BB), sbbe = succ_end(BB);
|
||||
if (sbbi==sbbe) {
|
||||
readEdgeOrRemember(getEdge(BB, 0),edgetocalc,uncalculated,outcount);
|
||||
}
|
||||
for (;sbbi != sbbe; ++sbbi) {
|
||||
if (succ_visited.insert(*sbbi)) {
|
||||
readEdgeOrRemember(getEdge(BB, *sbbi),edgetocalc,uncalculated,outcount);
|
||||
}
|
||||
}
|
||||
|
||||
// if exactly one edge weight was missing, calculate it and remove it from
|
||||
// spanning tree
|
||||
if (uncalculated == 1) {
|
||||
if (incount < outcount) {
|
||||
EdgeInformation[BB->getParent()][edgetocalc] = outcount-incount;
|
||||
} else {
|
||||
EdgeInformation[BB->getParent()][edgetocalc] = incount-outcount;
|
||||
}
|
||||
DEBUG(errs() << "--Calc Edge Counter for " << edgetocalc << ": "
|
||||
<< format("%g", getEdgeWeight(edgetocalc)) << "\n");
|
||||
SpanningTree.erase(edgetocalc);
|
||||
Edge tocalc;
|
||||
if (CalculateMissingEdge(BB, tocalc)) {
|
||||
SpanningTree.erase(tocalc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -219,9 +184,9 @@ bool LoaderPass::runOnModule(Module &M) {
|
||||
}
|
||||
}
|
||||
while (SpanningTree.size() > 0) {
|
||||
#if 0
|
||||
|
||||
unsigned size = SpanningTree.size();
|
||||
#endif
|
||||
|
||||
BBisUnvisited.clear();
|
||||
for (std::set<Edge>::iterator ei = SpanningTree.begin(),
|
||||
ee = SpanningTree.end(); ei != ee; ++ei) {
|
||||
@ -231,17 +196,16 @@ bool LoaderPass::runOnModule(Module &M) {
|
||||
while (BBisUnvisited.size() > 0) {
|
||||
recurseBasicBlock(*BBisUnvisited.begin());
|
||||
}
|
||||
#if 0
|
||||
|
||||
if (SpanningTree.size() == size) {
|
||||
DEBUG(errs()<<"{");
|
||||
for (std::set<Edge>::iterator ei = SpanningTree.begin(),
|
||||
ee = SpanningTree.end(); ei != ee; ++ei) {
|
||||
DEBUG(errs()<<"("<<(ei->first?ei->first->getName():"0")<<","
|
||||
<<(ei->second?ei->second->getName():"0")<<"),");
|
||||
DEBUG(errs()<< *ei <<",");
|
||||
}
|
||||
assert(0 && "No edge calculated!");
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
if (ReadCount != Counters.size()) {
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include "llvm/Support/InstIterator.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include <set>
|
||||
using namespace llvm;
|
||||
@ -29,44 +30,45 @@ static cl::opt<bool,false>
|
||||
ProfileVerifierDisableAssertions("profile-verifier-noassert",
|
||||
cl::desc("Disable assertions"));
|
||||
|
||||
namespace {
|
||||
class ProfileVerifierPass : public FunctionPass {
|
||||
namespace llvm {
|
||||
template<class FType, class BType>
|
||||
class ProfileVerifierPassT : public FunctionPass {
|
||||
|
||||
struct DetailedBlockInfo {
|
||||
const BasicBlock *BB;
|
||||
double BBWeight;
|
||||
double inWeight;
|
||||
int inCount;
|
||||
double outWeight;
|
||||
int outCount;
|
||||
const BType *BB;
|
||||
double BBWeight;
|
||||
double inWeight;
|
||||
int inCount;
|
||||
double outWeight;
|
||||
int outCount;
|
||||
};
|
||||
|
||||
ProfileInfo *PI;
|
||||
std::set<const BasicBlock*> BBisVisited;
|
||||
std::set<const Function*> FisVisited;
|
||||
ProfileInfoT<FType, BType> *PI;
|
||||
std::set<const BType*> BBisVisited;
|
||||
std::set<const FType*> FisVisited;
|
||||
bool DisableAssertions;
|
||||
|
||||
// When debugging is enabled, the verifier prints a whole slew of debug
|
||||
// information, otherwise its just the assert. These are all the helper
|
||||
// functions.
|
||||
bool PrintedDebugTree;
|
||||
std::set<const BasicBlock*> BBisPrinted;
|
||||
std::set<const BType*> BBisPrinted;
|
||||
void debugEntry(DetailedBlockInfo*);
|
||||
void printDebugInfo(const BasicBlock *BB);
|
||||
void printDebugInfo(const BType *BB);
|
||||
|
||||
public:
|
||||
static char ID; // Class identification, replacement for typeinfo
|
||||
|
||||
explicit ProfileVerifierPass () : FunctionPass(&ID) {
|
||||
explicit ProfileVerifierPassT () : FunctionPass(&ID) {
|
||||
DisableAssertions = ProfileVerifierDisableAssertions;
|
||||
}
|
||||
explicit ProfileVerifierPass (bool da) : FunctionPass(&ID),
|
||||
DisableAssertions(da) {
|
||||
explicit ProfileVerifierPassT (bool da) : FunctionPass(&ID),
|
||||
DisableAssertions(da) {
|
||||
}
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<ProfileInfo>();
|
||||
AU.addRequired<ProfileInfoT<FType, BType> >();
|
||||
}
|
||||
|
||||
const char *getPassName() const {
|
||||
@ -74,16 +76,296 @@ namespace {
|
||||
}
|
||||
|
||||
/// run - Verify the profile information.
|
||||
bool runOnFunction(Function &F);
|
||||
void recurseBasicBlock(const BasicBlock*);
|
||||
bool runOnFunction(FType &F);
|
||||
void recurseBasicBlock(const BType*);
|
||||
|
||||
bool exitReachable(const Function*);
|
||||
double ReadOrAssert(ProfileInfo::Edge);
|
||||
bool exitReachable(const FType*);
|
||||
double ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge);
|
||||
void CheckValue(bool, const char*, DetailedBlockInfo*);
|
||||
};
|
||||
} // End of anonymous namespace
|
||||
|
||||
char ProfileVerifierPass::ID = 0;
|
||||
typedef ProfileVerifierPassT<Function, BasicBlock> ProfileVerifierPass;
|
||||
|
||||
template<class FType, class BType>
|
||||
void ProfileVerifierPassT<FType, BType>::printDebugInfo(const BType *BB) {
|
||||
|
||||
if (BBisPrinted.find(BB) != BBisPrinted.end()) return;
|
||||
|
||||
double BBWeight = PI->getExecutionCount(BB);
|
||||
if (BBWeight == ProfileInfoT<FType, BType>::MissingValue) { BBWeight = 0; }
|
||||
double inWeight = 0;
|
||||
int inCount = 0;
|
||||
std::set<const BType*> ProcessedPreds;
|
||||
for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
if (ProcessedPreds.insert(*bbi).second) {
|
||||
typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(*bbi,BB);
|
||||
double EdgeWeight = PI->getEdgeWeight(E);
|
||||
if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; }
|
||||
errs() << "calculated in-edge " << E << ": "
|
||||
<< format("%20.20g",EdgeWeight) << "\n";
|
||||
inWeight += EdgeWeight;
|
||||
inCount++;
|
||||
}
|
||||
}
|
||||
double outWeight = 0;
|
||||
int outCount = 0;
|
||||
std::set<const BType*> ProcessedSuccs;
|
||||
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
if (ProcessedSuccs.insert(*bbi).second) {
|
||||
typename ProfileInfoT<FType, BType>::Edge E = PI->getEdge(BB,*bbi);
|
||||
double EdgeWeight = PI->getEdgeWeight(E);
|
||||
if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) { EdgeWeight = 0; }
|
||||
errs() << "calculated out-edge " << E << ": "
|
||||
<< format("%20.20g",EdgeWeight) << "\n";
|
||||
outWeight += EdgeWeight;
|
||||
outCount++;
|
||||
}
|
||||
}
|
||||
errs() << "Block " << BB->getNameStr() << " in "
|
||||
<< BB->getParent()->getNameStr() << ":"
|
||||
<< "BBWeight=" << format("%20.20g",BBWeight) << ","
|
||||
<< "inWeight=" << format("%20.20g",inWeight) << ","
|
||||
<< "inCount=" << inCount << ","
|
||||
<< "outWeight=" << format("%20.20g",outWeight) << ","
|
||||
<< "outCount" << outCount << "\n";
|
||||
|
||||
// mark as visited and recurse into subnodes
|
||||
BBisPrinted.insert(BB);
|
||||
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
printDebugInfo(*bbi);
|
||||
}
|
||||
}
|
||||
|
||||
template<class FType, class BType>
|
||||
void ProfileVerifierPassT<FType, BType>::debugEntry (DetailedBlockInfo *DI) {
|
||||
errs() << "TROUBLE: Block " << DI->BB->getNameStr() << " in "
|
||||
<< DI->BB->getParent()->getNameStr() << ":"
|
||||
<< "BBWeight=" << format("%20.20g",DI->BBWeight) << ","
|
||||
<< "inWeight=" << format("%20.20g",DI->inWeight) << ","
|
||||
<< "inCount=" << DI->inCount << ","
|
||||
<< "outWeight=" << format("%20.20g",DI->outWeight) << ","
|
||||
<< "outCount=" << DI->outCount << "\n";
|
||||
if (!PrintedDebugTree) {
|
||||
PrintedDebugTree = true;
|
||||
printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
|
||||
}
|
||||
}
|
||||
|
||||
// This compares A and B for equality.
|
||||
static bool Equals(double A, double B) {
|
||||
return A == B;
|
||||
}
|
||||
|
||||
// This checks if the function "exit" is reachable from an given function
|
||||
// via calls, this is necessary to check if a profile is valid despite the
|
||||
// counts not fitting exactly.
|
||||
template<class FType, class BType>
|
||||
bool ProfileVerifierPassT<FType, BType>::exitReachable(const FType *F) {
|
||||
if (!F) return false;
|
||||
|
||||
if (FisVisited.count(F)) return false;
|
||||
|
||||
FType *Exit = F->getParent()->getFunction("exit");
|
||||
if (Exit == F) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FisVisited.insert(F);
|
||||
bool exits = false;
|
||||
for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(&*I)) {
|
||||
FType *F = CI->getCalledFunction();
|
||||
if (F) {
|
||||
exits |= exitReachable(F);
|
||||
} else {
|
||||
// This is a call to a pointer, all bets are off...
|
||||
exits = true;
|
||||
}
|
||||
if (exits) break;
|
||||
}
|
||||
}
|
||||
return exits;
|
||||
}
|
||||
|
||||
#define ASSERTMESSAGE(M) \
|
||||
{ errs() << "ASSERT:" << (M) << "\n"; \
|
||||
if (!DisableAssertions) assert(0 && (M)); }
|
||||
|
||||
template<class FType, class BType>
|
||||
double ProfileVerifierPassT<FType, BType>::ReadOrAssert(typename ProfileInfoT<FType, BType>::Edge E) {
|
||||
double EdgeWeight = PI->getEdgeWeight(E);
|
||||
if (EdgeWeight == ProfileInfoT<FType, BType>::MissingValue) {
|
||||
errs() << "Edge " << E << " in Function "
|
||||
<< ProfileInfoT<FType, BType>::getFunction(E)->getNameStr() << ": ";
|
||||
ASSERTMESSAGE("Edge has missing value");
|
||||
return 0;
|
||||
} else {
|
||||
if (EdgeWeight < 0) {
|
||||
errs() << "Edge " << E << " in Function "
|
||||
<< ProfileInfoT<FType, BType>::getFunction(E)->getNameStr() << ": ";
|
||||
ASSERTMESSAGE("Edge has negative value");
|
||||
}
|
||||
return EdgeWeight;
|
||||
}
|
||||
}
|
||||
|
||||
template<class FType, class BType>
|
||||
void ProfileVerifierPassT<FType, BType>::CheckValue(bool Error,
|
||||
const char *Message,
|
||||
DetailedBlockInfo *DI) {
|
||||
if (Error) {
|
||||
DEBUG(debugEntry(DI));
|
||||
errs() << "Block " << DI->BB->getNameStr() << " in Function "
|
||||
<< DI->BB->getParent()->getNameStr() << ": ";
|
||||
ASSERTMESSAGE(Message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// This calculates the Information for a block and then recurses into the
|
||||
// successors.
|
||||
template<class FType, class BType>
|
||||
void ProfileVerifierPassT<FType, BType>::recurseBasicBlock(const BType *BB) {
|
||||
|
||||
// Break the recursion by remembering all visited blocks.
|
||||
if (BBisVisited.find(BB) != BBisVisited.end()) return;
|
||||
|
||||
// Use a data structure to store all the information, this can then be handed
|
||||
// to debug printers.
|
||||
DetailedBlockInfo DI;
|
||||
DI.BB = BB;
|
||||
DI.outCount = DI.inCount = 0;
|
||||
DI.inWeight = DI.outWeight = 0;
|
||||
|
||||
// Read predecessors.
|
||||
std::set<const BType*> ProcessedPreds;
|
||||
pred_const_iterator bpi = pred_begin(BB), bpe = pred_end(BB);
|
||||
// If there are none, check for (0,BB) edge.
|
||||
if (bpi == bpe) {
|
||||
DI.inWeight += ReadOrAssert(PI->getEdge(0,BB));
|
||||
DI.inCount++;
|
||||
}
|
||||
for (;bpi != bpe; ++bpi) {
|
||||
if (ProcessedPreds.insert(*bpi).second) {
|
||||
DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB));
|
||||
DI.inCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Read successors.
|
||||
std::set<const BType*> ProcessedSuccs;
|
||||
succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||
// If there is an (0,BB) edge, consider it too. (This is done not only when
|
||||
// there are no successors, but every time; not every function contains
|
||||
// return blocks with no successors (think loop latch as return block)).
|
||||
double w = PI->getEdgeWeight(PI->getEdge(BB,0));
|
||||
if (w != ProfileInfoT<FType, BType>::MissingValue) {
|
||||
DI.outWeight += w;
|
||||
DI.outCount++;
|
||||
}
|
||||
for (;bbi != bbe; ++bbi) {
|
||||
if (ProcessedSuccs.insert(*bbi).second) {
|
||||
DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
|
||||
DI.outCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Read block weight.
|
||||
DI.BBWeight = PI->getExecutionCount(BB);
|
||||
CheckValue(DI.BBWeight == ProfileInfoT<FType, BType>::MissingValue,
|
||||
"BasicBlock has missing value", &DI);
|
||||
CheckValue(DI.BBWeight < 0,
|
||||
"BasicBlock has negative value", &DI);
|
||||
|
||||
// Check if this block is a setjmp target.
|
||||
bool isSetJmpTarget = false;
|
||||
if (DI.outWeight > DI.inWeight) {
|
||||
for (typename BType::const_iterator i = BB->begin(), ie = BB->end();
|
||||
i != ie; ++i) {
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
|
||||
FType *F = CI->getCalledFunction();
|
||||
if (F && (F->getNameStr() == "_setjmp")) {
|
||||
isSetJmpTarget = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if this block is eventually reaching exit.
|
||||
bool isExitReachable = false;
|
||||
if (DI.inWeight > DI.outWeight) {
|
||||
for (typename BType::const_iterator i = BB->begin(), ie = BB->end();
|
||||
i != ie; ++i) {
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
|
||||
FType *F = CI->getCalledFunction();
|
||||
if (F) {
|
||||
FisVisited.clear();
|
||||
isExitReachable |= exitReachable(F);
|
||||
} else {
|
||||
// This is a call to a pointer, all bets are off...
|
||||
isExitReachable = true;
|
||||
}
|
||||
if (isExitReachable) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DI.inCount > 0 && DI.outCount == 0) {
|
||||
// If this is a block with no successors.
|
||||
if (!isSetJmpTarget) {
|
||||
CheckValue(!Equals(DI.inWeight,DI.BBWeight),
|
||||
"inWeight and BBWeight do not match", &DI);
|
||||
}
|
||||
} else if (DI.inCount == 0 && DI.outCount > 0) {
|
||||
// If this is a block with no predecessors.
|
||||
if (!isExitReachable)
|
||||
CheckValue(!Equals(DI.BBWeight,DI.outWeight),
|
||||
"BBWeight and outWeight do not match", &DI);
|
||||
} else {
|
||||
// If this block has successors and predecessors.
|
||||
if (DI.inWeight > DI.outWeight && !isExitReachable)
|
||||
CheckValue(!Equals(DI.inWeight,DI.outWeight),
|
||||
"inWeight and outWeight do not match", &DI);
|
||||
if (DI.inWeight < DI.outWeight && !isSetJmpTarget)
|
||||
CheckValue(!Equals(DI.inWeight,DI.outWeight),
|
||||
"inWeight and outWeight do not match", &DI);
|
||||
}
|
||||
|
||||
|
||||
// Mark this block as visited, rescurse into successors.
|
||||
BBisVisited.insert(BB);
|
||||
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
recurseBasicBlock(*bbi);
|
||||
}
|
||||
}
|
||||
|
||||
template<class FType, class BType>
|
||||
bool ProfileVerifierPassT<FType, BType>::runOnFunction(FType &F) {
|
||||
PI = getAnalysisIfAvailable<ProfileInfoT<FType, BType> >();
|
||||
if (!PI)
|
||||
ASSERTMESSAGE("No ProfileInfo available");
|
||||
|
||||
// Prepare global variables.
|
||||
PrintedDebugTree = false;
|
||||
BBisVisited.clear();
|
||||
|
||||
// Fetch entry block and recurse into it.
|
||||
const BType *entry = &F.getEntryBlock();
|
||||
recurseBasicBlock(entry);
|
||||
|
||||
if (PI->getExecutionCount(&F) != PI->getExecutionCount(entry))
|
||||
ASSERTMESSAGE("Function count and entry block count do not match");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class FType, class BType>
|
||||
char ProfileVerifierPassT<FType, BType>::ID = 0;
|
||||
}
|
||||
|
||||
static RegisterPass<ProfileVerifierPass>
|
||||
X("profile-verifier", "Verify profiling information", false, true);
|
||||
|
||||
@ -93,252 +375,3 @@ namespace llvm {
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileVerifierPass::printDebugInfo(const BasicBlock *BB) {
|
||||
|
||||
if (BBisPrinted.find(BB) != BBisPrinted.end()) return;
|
||||
|
||||
double BBWeight = PI->getExecutionCount(BB);
|
||||
if (BBWeight == ProfileInfo::MissingValue) { BBWeight = 0; }
|
||||
double inWeight = 0;
|
||||
int inCount = 0;
|
||||
std::set<const BasicBlock*> ProcessedPreds;
|
||||
for ( pred_const_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
if (ProcessedPreds.insert(*bbi).second) {
|
||||
ProfileInfo::Edge E = PI->getEdge(*bbi,BB);
|
||||
double EdgeWeight = PI->getEdgeWeight(E);
|
||||
if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
|
||||
errs() << "calculated in-edge " << E << ": " << EdgeWeight << "\n";
|
||||
inWeight += EdgeWeight;
|
||||
inCount++;
|
||||
}
|
||||
}
|
||||
double outWeight = 0;
|
||||
int outCount = 0;
|
||||
std::set<const BasicBlock*> ProcessedSuccs;
|
||||
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
if (ProcessedSuccs.insert(*bbi).second) {
|
||||
ProfileInfo::Edge E = PI->getEdge(BB,*bbi);
|
||||
double EdgeWeight = PI->getEdgeWeight(E);
|
||||
if (EdgeWeight == ProfileInfo::MissingValue) { EdgeWeight = 0; }
|
||||
errs() << "calculated out-edge " << E << ": " << EdgeWeight << "\n";
|
||||
outWeight += EdgeWeight;
|
||||
outCount++;
|
||||
}
|
||||
}
|
||||
errs()<<"Block "<<BB->getNameStr()<<" in "<<BB->getParent()->getNameStr()
|
||||
<<",BBWeight="<<BBWeight<<",inWeight="<<inWeight<<",inCount="<<inCount
|
||||
<<",outWeight="<<outWeight<<",outCount"<<outCount<<"\n";
|
||||
|
||||
// mark as visited and recurse into subnodes
|
||||
BBisPrinted.insert(BB);
|
||||
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
printDebugInfo(*bbi);
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileVerifierPass::debugEntry (DetailedBlockInfo *DI) {
|
||||
errs() << "TROUBLE: Block " << DI->BB->getNameStr() << " in "
|
||||
<< DI->BB->getParent()->getNameStr() << ":";
|
||||
errs() << "BBWeight=" << DI->BBWeight << ",";
|
||||
errs() << "inWeight=" << DI->inWeight << ",";
|
||||
errs() << "inCount=" << DI->inCount << ",";
|
||||
errs() << "outWeight=" << DI->outWeight << ",";
|
||||
errs() << "outCount=" << DI->outCount << "\n";
|
||||
if (!PrintedDebugTree) {
|
||||
PrintedDebugTree = true;
|
||||
printDebugInfo(&(DI->BB->getParent()->getEntryBlock()));
|
||||
}
|
||||
}
|
||||
|
||||
// This compares A and B but considering maybe small differences.
|
||||
static bool Equals(double A, double B) {
|
||||
double maxRelativeError = 0.0000001;
|
||||
if (A == B)
|
||||
return true;
|
||||
double relativeError;
|
||||
if (fabs(B) > fabs(A))
|
||||
relativeError = fabs((A - B) / B);
|
||||
else
|
||||
relativeError = fabs((A - B) / A);
|
||||
if (relativeError <= maxRelativeError) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// This checks if the function "exit" is reachable from an given function
|
||||
// via calls, this is necessary to check if a profile is valid despite the
|
||||
// counts not fitting exactly.
|
||||
bool ProfileVerifierPass::exitReachable(const Function *F) {
|
||||
if (!F) return false;
|
||||
|
||||
if (FisVisited.count(F)) return false;
|
||||
|
||||
Function *Exit = F->getParent()->getFunction("exit");
|
||||
if (Exit == F) {
|
||||
return true;
|
||||
}
|
||||
|
||||
FisVisited.insert(F);
|
||||
bool exits = false;
|
||||
for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(&*I)) {
|
||||
exits |= exitReachable(CI->getCalledFunction());
|
||||
if (exits) break;
|
||||
}
|
||||
}
|
||||
return exits;
|
||||
}
|
||||
|
||||
#define ASSERTMESSAGE(M) \
|
||||
errs() << (M) << "\n"; \
|
||||
if (!DisableAssertions) assert(0 && (M));
|
||||
|
||||
double ProfileVerifierPass::ReadOrAssert(ProfileInfo::Edge E) {
|
||||
double EdgeWeight = PI->getEdgeWeight(E);
|
||||
if (EdgeWeight == ProfileInfo::MissingValue) {
|
||||
errs() << "Edge " << E << " in Function "
|
||||
<< ProfileInfo::getFunction(E)->getNameStr() << ": ";
|
||||
ASSERTMESSAGE("ASSERT:Edge has missing value");
|
||||
return 0;
|
||||
} else {
|
||||
return EdgeWeight;
|
||||
}
|
||||
}
|
||||
|
||||
void ProfileVerifierPass::CheckValue(bool Error, const char *Message,
|
||||
DetailedBlockInfo *DI) {
|
||||
if (Error) {
|
||||
DEBUG(debugEntry(DI));
|
||||
errs() << "Block " << DI->BB->getNameStr() << " in Function "
|
||||
<< DI->BB->getParent()->getNameStr() << ": ";
|
||||
ASSERTMESSAGE(Message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// This calculates the Information for a block and then recurses into the
|
||||
// successors.
|
||||
void ProfileVerifierPass::recurseBasicBlock(const BasicBlock *BB) {
|
||||
|
||||
// Break the recursion by remembering all visited blocks.
|
||||
if (BBisVisited.find(BB) != BBisVisited.end()) return;
|
||||
|
||||
// Use a data structure to store all the information, this can then be handed
|
||||
// to debug printers.
|
||||
DetailedBlockInfo DI;
|
||||
DI.BB = BB;
|
||||
DI.outCount = DI.inCount = 0;
|
||||
DI.inWeight = DI.outWeight = 0.0;
|
||||
|
||||
// Read predecessors.
|
||||
std::set<const BasicBlock*> ProcessedPreds;
|
||||
pred_const_iterator bpi = pred_begin(BB), bpe = pred_end(BB);
|
||||
// If there are none, check for (0,BB) edge.
|
||||
if (bpi == bpe) {
|
||||
DI.inWeight += ReadOrAssert(PI->getEdge(0,BB));
|
||||
DI.inCount++;
|
||||
}
|
||||
for (;bpi != bpe; ++bpi) {
|
||||
if (ProcessedPreds.insert(*bpi).second) {
|
||||
DI.inWeight += ReadOrAssert(PI->getEdge(*bpi,BB));
|
||||
DI.inCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Read successors.
|
||||
std::set<const BasicBlock*> ProcessedSuccs;
|
||||
succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||
// If there is an (0,BB) edge, consider it too. (This is done not only when
|
||||
// there are no successors, but every time; not every function contains
|
||||
// return blocks with no successors (think loop latch as return block)).
|
||||
double w = PI->getEdgeWeight(PI->getEdge(BB,0));
|
||||
if (w != ProfileInfo::MissingValue) {
|
||||
DI.outWeight += w;
|
||||
DI.outCount++;
|
||||
}
|
||||
for (;bbi != bbe; ++bbi) {
|
||||
if (ProcessedSuccs.insert(*bbi).second) {
|
||||
DI.outWeight += ReadOrAssert(PI->getEdge(BB,*bbi));
|
||||
DI.outCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Read block weight.
|
||||
DI.BBWeight = PI->getExecutionCount(BB);
|
||||
CheckValue(DI.BBWeight == ProfileInfo::MissingValue,
|
||||
"ASSERT:BasicBlock has missing value", &DI);
|
||||
|
||||
// Check if this block is a setjmp target.
|
||||
bool isSetJmpTarget = false;
|
||||
if (DI.outWeight > DI.inWeight) {
|
||||
for (BasicBlock::const_iterator i = BB->begin(), ie = BB->end();
|
||||
i != ie; ++i) {
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
|
||||
Function *F = CI->getCalledFunction();
|
||||
if (F && (F->getNameStr() == "_setjmp")) {
|
||||
isSetJmpTarget = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if this block is eventually reaching exit.
|
||||
bool isExitReachable = false;
|
||||
if (DI.inWeight > DI.outWeight) {
|
||||
for (BasicBlock::const_iterator i = BB->begin(), ie = BB->end();
|
||||
i != ie; ++i) {
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(&*i)) {
|
||||
FisVisited.clear();
|
||||
isExitReachable |= exitReachable(CI->getCalledFunction());
|
||||
if (isExitReachable) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DI.inCount > 0 && DI.outCount == 0) {
|
||||
// If this is a block with no successors.
|
||||
if (!isSetJmpTarget) {
|
||||
CheckValue(!Equals(DI.inWeight,DI.BBWeight),
|
||||
"ASSERT:inWeight and BBWeight do not match", &DI);
|
||||
}
|
||||
} else if (DI.inCount == 0 && DI.outCount > 0) {
|
||||
// If this is a block with no predecessors.
|
||||
if (!isExitReachable)
|
||||
CheckValue(!Equals(DI.BBWeight,DI.outWeight),
|
||||
"ASSERT:BBWeight and outWeight do not match", &DI);
|
||||
} else {
|
||||
// If this block has successors and predecessors.
|
||||
if (DI.inWeight > DI.outWeight && !isExitReachable)
|
||||
CheckValue(!Equals(DI.inWeight,DI.outWeight),
|
||||
"ASSERT:inWeight and outWeight do not match", &DI);
|
||||
if (DI.inWeight < DI.outWeight && !isSetJmpTarget)
|
||||
CheckValue(!Equals(DI.inWeight,DI.outWeight),
|
||||
"ASSERT:inWeight and outWeight do not match", &DI);
|
||||
}
|
||||
|
||||
|
||||
// Mark this block as visited, rescurse into successors.
|
||||
BBisVisited.insert(BB);
|
||||
for ( succ_const_iterator bbi = succ_begin(BB), bbe = succ_end(BB);
|
||||
bbi != bbe; ++bbi ) {
|
||||
recurseBasicBlock(*bbi);
|
||||
}
|
||||
}
|
||||
|
||||
bool ProfileVerifierPass::runOnFunction(Function &F) {
|
||||
PI = &getAnalysis<ProfileInfo>();
|
||||
|
||||
// Prepare global variables.
|
||||
PrintedDebugTree = false;
|
||||
BBisVisited.clear();
|
||||
|
||||
// Fetch entry block and recurse into it.
|
||||
const BasicBlock *entry = &F.getEntryBlock();
|
||||
recurseBasicBlock(entry);
|
||||
|
||||
if (!DisableAssertions)
|
||||
assert((PI->getExecutionCount(&F)==PI->getExecutionCount(entry)) &&
|
||||
"Function count and entry block count do not match");
|
||||
return false;
|
||||
}
|
||||
|
@ -357,7 +357,7 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin,
|
||||
// without the other.
|
||||
SplitAddRecs(Ops, Ty, SE);
|
||||
|
||||
// Decend down the pointer's type and attempt to convert the other
|
||||
// Descend down the pointer's type and attempt to convert the other
|
||||
// operands into GEP indices, at each level. The first index in a GEP
|
||||
// indexes into the array implied by the pointer operand; the rest of
|
||||
// the indices index into the element or field type selected by the
|
||||
@ -628,7 +628,7 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
|
||||
BasicBlock *SaveInsertBB = Builder.GetInsertBlock();
|
||||
BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint();
|
||||
BasicBlock::iterator NewInsertPt =
|
||||
next(BasicBlock::iterator(cast<Instruction>(V)));
|
||||
llvm::next(BasicBlock::iterator(cast<Instruction>(V)));
|
||||
while (isa<PHINode>(NewInsertPt)) ++NewInsertPt;
|
||||
V = expandCodeFor(SE.getTruncateExpr(SE.getUnknown(V), Ty), 0,
|
||||
NewInsertPt);
|
||||
@ -844,7 +844,7 @@ Value *SCEVExpander::expand(const SCEV *S) {
|
||||
if (L && S->hasComputableLoopEvolution(L))
|
||||
InsertPt = L->getHeader()->getFirstNonPHI();
|
||||
while (isInsertedInstruction(InsertPt))
|
||||
InsertPt = next(BasicBlock::iterator(InsertPt));
|
||||
InsertPt = llvm::next(BasicBlock::iterator(InsertPt));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -659,7 +659,7 @@ unsigned llvm::ComputeNumSignBits(Value *V, const TargetData *TD,
|
||||
switch (Operator::getOpcode(V)) {
|
||||
default: break;
|
||||
case Instruction::SExt:
|
||||
Tmp = TyBits-cast<IntegerType>(U->getOperand(0)->getType())->getBitWidth();
|
||||
Tmp = TyBits - U->getOperand(0)->getType()->getScalarSizeInBits();
|
||||
return ComputeNumSignBits(U->getOperand(0), TD, Depth+1) + Tmp;
|
||||
|
||||
case Instruction::AShr:
|
||||
|
@ -540,6 +540,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(arm_apcscc);
|
||||
KEYWORD(arm_aapcscc);
|
||||
KEYWORD(arm_aapcs_vfpcc);
|
||||
KEYWORD(msp430_intrcc);
|
||||
|
||||
KEYWORD(cc);
|
||||
KEYWORD(c);
|
||||
|
@ -581,6 +581,37 @@ bool LLParser::ParseStandaloneMetadata() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseInlineMetadata:
|
||||
/// !{type %instr}
|
||||
/// !{...} MDNode
|
||||
/// !"foo" MDString
|
||||
bool LLParser::ParseInlineMetadata(Value *&V, PerFunctionState &PFS) {
|
||||
assert(Lex.getKind() == lltok::Metadata && "Only for Metadata");
|
||||
V = 0;
|
||||
|
||||
Lex.Lex();
|
||||
if (Lex.getKind() == lltok::lbrace) {
|
||||
Lex.Lex();
|
||||
if (ParseTypeAndValue(V, PFS) ||
|
||||
ParseToken(lltok::rbrace, "expected end of metadata node"))
|
||||
return true;
|
||||
|
||||
Value *Vals[] = { V };
|
||||
V = MDNode::get(Context, Vals, 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Standalone metadata reference
|
||||
// !{ ..., !42, ... }
|
||||
if (!ParseMDNode((MetadataBase *&)V))
|
||||
return false;
|
||||
|
||||
// MDString:
|
||||
// '!' STRINGCONSTANT
|
||||
if (ParseMDString((MetadataBase *&)V)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseAlias:
|
||||
/// ::= GlobalVar '=' OptionalVisibility 'alias' OptionalLinkage Aliasee
|
||||
/// Aliasee
|
||||
@ -1043,6 +1074,7 @@ bool LLParser::ParseOptionalVisibility(unsigned &Res) {
|
||||
/// ::= 'arm_apcscc'
|
||||
/// ::= 'arm_aapcscc'
|
||||
/// ::= 'arm_aapcs_vfpcc'
|
||||
/// ::= 'msp430_intrcc'
|
||||
/// ::= 'cc' UINT
|
||||
///
|
||||
bool LLParser::ParseOptionalCallingConv(CallingConv::ID &CC) {
|
||||
@ -1056,6 +1088,7 @@ bool LLParser::ParseOptionalCallingConv(CallingConv::ID &CC) {
|
||||
case lltok::kw_arm_apcscc: CC = CallingConv::ARM_APCS; break;
|
||||
case lltok::kw_arm_aapcscc: CC = CallingConv::ARM_AAPCS; break;
|
||||
case lltok::kw_arm_aapcs_vfpcc:CC = CallingConv::ARM_AAPCS_VFP; break;
|
||||
case lltok::kw_msp430_intrcc: CC = CallingConv::MSP430_INTR; break;
|
||||
case lltok::kw_cc: {
|
||||
unsigned ArbitraryCC;
|
||||
Lex.Lex();
|
||||
@ -1377,15 +1410,23 @@ bool LLParser::ParseParameterList(SmallVectorImpl<ParamInfo> &ArgList,
|
||||
// Parse the argument.
|
||||
LocTy ArgLoc;
|
||||
PATypeHolder ArgTy(Type::getVoidTy(Context));
|
||||
unsigned ArgAttrs1, ArgAttrs2;
|
||||
unsigned ArgAttrs1 = Attribute::None;
|
||||
unsigned ArgAttrs2 = Attribute::None;
|
||||
Value *V;
|
||||
if (ParseType(ArgTy, ArgLoc) ||
|
||||
ParseOptionalAttrs(ArgAttrs1, 0) ||
|
||||
ParseValue(ArgTy, V, PFS) ||
|
||||
// FIXME: Should not allow attributes after the argument, remove this in
|
||||
// LLVM 3.0.
|
||||
ParseOptionalAttrs(ArgAttrs2, 3))
|
||||
if (ParseType(ArgTy, ArgLoc))
|
||||
return true;
|
||||
|
||||
if (Lex.getKind() == lltok::Metadata) {
|
||||
if (ParseInlineMetadata(V, PFS))
|
||||
return true;
|
||||
} else {
|
||||
if (ParseOptionalAttrs(ArgAttrs1, 0) ||
|
||||
ParseValue(ArgTy, V, PFS) ||
|
||||
// FIXME: Should not allow attributes after the argument, remove this
|
||||
// in LLVM 3.0.
|
||||
ParseOptionalAttrs(ArgAttrs2, 3))
|
||||
return true;
|
||||
}
|
||||
ArgList.push_back(ParamInfo(ArgLoc, V, ArgAttrs1|ArgAttrs2));
|
||||
}
|
||||
|
||||
|
@ -279,7 +279,9 @@ namespace llvm {
|
||||
LocTy Loc;
|
||||
return ParseTypeAndBasicBlock(BB, Loc, PFS);
|
||||
}
|
||||
|
||||
|
||||
bool ParseInlineMetadata(Value *&V, PerFunctionState &PFS);
|
||||
|
||||
struct ParamInfo {
|
||||
LocTy Loc;
|
||||
Value *V;
|
||||
|
@ -69,6 +69,7 @@ namespace lltok {
|
||||
kw_cc, kw_ccc, kw_fastcc, kw_coldcc,
|
||||
kw_x86_stdcallcc, kw_x86_fastcallcc,
|
||||
kw_arm_apcscc, kw_arm_aapcscc, kw_arm_aapcs_vfpcc,
|
||||
kw_msp430_intrcc,
|
||||
|
||||
kw_signext,
|
||||
kw_zeroext,
|
||||
|
@ -413,7 +413,7 @@ uintptr_t Deserializer::ReadInternalRefPtr() {
|
||||
return GetFinalPtr(E);
|
||||
}
|
||||
|
||||
void Deserializer::BPEntry::SetPtr(BPNode*& FreeList, void* P) {
|
||||
void BPEntry::SetPtr(BPNode*& FreeList, void* P) {
|
||||
BPNode* Last = NULL;
|
||||
|
||||
for (BPNode* N = Head; N != NULL; N=N->Next) {
|
||||
|
@ -38,16 +38,19 @@ DebugMod("agg-antidep-debugmod",
|
||||
cl::desc("Debug control for aggressive anti-dep breaker"),
|
||||
cl::init(0), cl::Hidden);
|
||||
|
||||
AggressiveAntiDepState::AggressiveAntiDepState(MachineBasicBlock *BB) :
|
||||
GroupNodes(TargetRegisterInfo::FirstVirtualRegister, 0) {
|
||||
// Initialize all registers to be in their own group. Initially we
|
||||
// assign the register to the same-indexed GroupNode.
|
||||
for (unsigned i = 0; i < TargetRegisterInfo::FirstVirtualRegister; ++i)
|
||||
GroupNodeIndices[i] = i;
|
||||
AggressiveAntiDepState::AggressiveAntiDepState(const unsigned TargetRegs,
|
||||
MachineBasicBlock *BB) :
|
||||
NumTargetRegs(TargetRegs), GroupNodes(TargetRegs, 0) {
|
||||
|
||||
// Initialize the indices to indicate that no registers are live.
|
||||
std::fill(KillIndices, array_endof(KillIndices), ~0u);
|
||||
std::fill(DefIndices, array_endof(DefIndices), BB->size());
|
||||
const unsigned BBSize = BB->size();
|
||||
for (unsigned i = 0; i < NumTargetRegs; ++i) {
|
||||
// Initialize all registers to be in their own group. Initially we
|
||||
// assign the register to the same-indexed GroupNode.
|
||||
GroupNodeIndices[i] = i;
|
||||
// Initialize the indices to indicate that no registers are live.
|
||||
KillIndices[i] = ~0u;
|
||||
DefIndices[i] = BBSize;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned AggressiveAntiDepState::GetGroup(unsigned Reg)
|
||||
@ -64,7 +67,7 @@ void AggressiveAntiDepState::GetGroupRegs(
|
||||
std::vector<unsigned> &Regs,
|
||||
std::multimap<unsigned, AggressiveAntiDepState::RegisterReference> *RegRefs)
|
||||
{
|
||||
for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) {
|
||||
for (unsigned Reg = 0; Reg != NumTargetRegs; ++Reg) {
|
||||
if ((GetGroup(Reg) == Group) && (RegRefs->count(Reg) > 0))
|
||||
Regs.push_back(Reg);
|
||||
}
|
||||
@ -137,7 +140,7 @@ AggressiveAntiDepBreaker::~AggressiveAntiDepBreaker() {
|
||||
|
||||
void AggressiveAntiDepBreaker::StartBlock(MachineBasicBlock *BB) {
|
||||
assert(State == NULL);
|
||||
State = new AggressiveAntiDepState(BB);
|
||||
State = new AggressiveAntiDepState(TRI->getNumRegs(), BB);
|
||||
|
||||
bool IsReturnBlock = (!BB->empty() && BB->back().getDesc().isReturn());
|
||||
unsigned *KillIndices = State->GetKillIndices();
|
||||
@ -220,7 +223,7 @@ void AggressiveAntiDepBreaker::Observe(MachineInstr *MI, unsigned Count,
|
||||
DEBUG(errs() << "\tRegs:");
|
||||
|
||||
unsigned *DefIndices = State->GetDefIndices();
|
||||
for (unsigned Reg = 0; Reg != TargetRegisterInfo::FirstVirtualRegister; ++Reg) {
|
||||
for (unsigned Reg = 0; Reg != TRI->getNumRegs(); ++Reg) {
|
||||
// If Reg is current live, then mark that it can't be renamed as
|
||||
// we don't know the extent of its live-range anymore (now that it
|
||||
// has been scheduled). If it is not live but was defined in the
|
||||
|
@ -44,6 +44,10 @@ namespace llvm {
|
||||
} RegisterReference;
|
||||
|
||||
private:
|
||||
/// NumTargetRegs - Number of non-virtual target registers
|
||||
/// (i.e. TRI->getNumRegs()).
|
||||
const unsigned NumTargetRegs;
|
||||
|
||||
/// GroupNodes - Implements a disjoint-union data structure to
|
||||
/// form register groups. A node is represented by an index into
|
||||
/// the vector. A node can "point to" itself to indicate that it
|
||||
@ -69,7 +73,7 @@ namespace llvm {
|
||||
unsigned DefIndices[TargetRegisterInfo::FirstVirtualRegister];
|
||||
|
||||
public:
|
||||
AggressiveAntiDepState(MachineBasicBlock *BB);
|
||||
AggressiveAntiDepState(const unsigned TargetRegs, MachineBasicBlock *BB);
|
||||
|
||||
/// GetKillIndices - Return the kill indices.
|
||||
unsigned *GetKillIndices() { return KillIndices; }
|
||||
|
@ -1374,6 +1374,7 @@ void AsmPrinter::processDebugLoc(const MachineInstr *MI,
|
||||
unsigned L = DW->RecordSourceLine(CurDLT.Line, CurDLT.Col,
|
||||
CurDLT.Scope);
|
||||
printLabel(L);
|
||||
O << '\n';
|
||||
DW->BeginScope(MI, L);
|
||||
PrevDLT = CurDLT;
|
||||
}
|
||||
@ -1837,15 +1838,16 @@ void AsmPrinter::EmitComments(const MachineInstr &MI) const {
|
||||
|
||||
// Print source line info.
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << " SrcLine ";
|
||||
if (DLT.Scope) {
|
||||
DICompileUnit CU(DLT.Scope);
|
||||
if (!CU.isNull())
|
||||
O << CU.getFilename() << " ";
|
||||
}
|
||||
O << DLT.Line;
|
||||
O << MAI->getCommentString() << ' ';
|
||||
DIScope Scope(DLT.Scope);
|
||||
// Omit the directory, because it's likely to be long and uninteresting.
|
||||
if (!Scope.isNull())
|
||||
O << Scope.getFilename();
|
||||
else
|
||||
O << "<unknown>";
|
||||
O << ':' << DLT.Line;
|
||||
if (DLT.Col != 0)
|
||||
O << ":" << DLT.Col;
|
||||
O << ':' << DLT.Col;
|
||||
Newline = true;
|
||||
}
|
||||
|
||||
@ -1857,35 +1859,40 @@ void AsmPrinter::EmitComments(const MachineInstr &MI) const {
|
||||
|
||||
// We assume a single instruction only has a spill or reload, not
|
||||
// both.
|
||||
const MachineMemOperand *MMO;
|
||||
if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) {
|
||||
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
|
||||
MMO = *MI.memoperands_begin();
|
||||
if (Newline) O << '\n';
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << " Reload";
|
||||
O << MAI->getCommentString() << ' ' << MMO->getSize() << "-byte Reload";
|
||||
Newline = true;
|
||||
}
|
||||
}
|
||||
else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, FI)) {
|
||||
else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) {
|
||||
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
|
||||
if (Newline) O << '\n';
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << " Folded Reload";
|
||||
O << MAI->getCommentString() << ' '
|
||||
<< MMO->getSize() << "-byte Folded Reload";
|
||||
Newline = true;
|
||||
}
|
||||
}
|
||||
else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) {
|
||||
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
|
||||
MMO = *MI.memoperands_begin();
|
||||
if (Newline) O << '\n';
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << " Spill";
|
||||
O << MAI->getCommentString() << ' ' << MMO->getSize() << "-byte Spill";
|
||||
Newline = true;
|
||||
}
|
||||
}
|
||||
else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, FI)) {
|
||||
else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) {
|
||||
if (FrameInfo->isSpillSlotObjectIndex(FI)) {
|
||||
if (Newline) O << '\n';
|
||||
O.PadToColumn(MAI->getCommentColumn());
|
||||
O << MAI->getCommentString() << " Folded Spill";
|
||||
O << MAI->getCommentString() << ' '
|
||||
<< MMO->getSize() << "-byte Folded Spill";
|
||||
Newline = true;
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ namespace llvm {
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// DIEString - A string value DIE.
|
||||
/// DIEString - A string value DIE. This DIE keeps string reference only.
|
||||
///
|
||||
class DIEString : public DIEValue {
|
||||
const StringRef Str;
|
||||
|
@ -330,8 +330,8 @@ void DwarfDebug::addSInt(DIE *Die, unsigned Attribute,
|
||||
Die->addValue(Attribute, Form, Value);
|
||||
}
|
||||
|
||||
/// addString - Add a string attribute data and value.
|
||||
///
|
||||
/// addString - Add a string attribute data and value. DIEString only
|
||||
/// keeps string reference.
|
||||
void DwarfDebug::addString(DIE *Die, unsigned Attribute, unsigned Form,
|
||||
const StringRef String) {
|
||||
DIEValue *Value = new DIEString(String);
|
||||
@ -393,7 +393,7 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIVariable *V) {
|
||||
return;
|
||||
|
||||
unsigned Line = V->getLineNumber();
|
||||
unsigned FileID = findCompileUnit(V->getCompileUnit()).getID();
|
||||
unsigned FileID = findCompileUnit(V->getCompileUnit())->getID();
|
||||
assert(FileID && "Invalid file id");
|
||||
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
|
||||
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
|
||||
@ -407,7 +407,7 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIGlobal *G) {
|
||||
return;
|
||||
|
||||
unsigned Line = G->getLineNumber();
|
||||
unsigned FileID = findCompileUnit(G->getCompileUnit()).getID();
|
||||
unsigned FileID = findCompileUnit(G->getCompileUnit())->getID();
|
||||
assert(FileID && "Invalid file id");
|
||||
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
|
||||
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
|
||||
@ -425,7 +425,7 @@ void DwarfDebug::addSourceLine(DIE *Die, const DISubprogram *SP) {
|
||||
|
||||
|
||||
unsigned Line = SP->getLineNumber();
|
||||
unsigned FileID = findCompileUnit(SP->getCompileUnit()).getID();
|
||||
unsigned FileID = findCompileUnit(SP->getCompileUnit())->getID();
|
||||
assert(FileID && "Invalid file id");
|
||||
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
|
||||
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
|
||||
@ -440,7 +440,7 @@ void DwarfDebug::addSourceLine(DIE *Die, const DIType *Ty) {
|
||||
return;
|
||||
|
||||
unsigned Line = Ty->getLineNumber();
|
||||
unsigned FileID = findCompileUnit(CU).getID();
|
||||
unsigned FileID = findCompileUnit(CU)->getID();
|
||||
assert(FileID && "Invalid file id");
|
||||
addUInt(Die, dwarf::DW_AT_decl_file, 0, FileID);
|
||||
addUInt(Die, dwarf::DW_AT_decl_line, 0, Line);
|
||||
@ -738,13 +738,49 @@ void DwarfDebug::addAddress(DIE *Die, unsigned Attribute,
|
||||
addBlock(Die, Attribute, 0, Block);
|
||||
}
|
||||
|
||||
/// addToContextOwner - Add Die into the list of its context owner's children.
|
||||
void DwarfDebug::addToContextOwner(DIE *Die, DIDescriptor Context) {
|
||||
if (Context.isNull())
|
||||
ModuleCU->addDie(Die);
|
||||
else if (Context.isType()) {
|
||||
DIE *ContextDIE = getOrCreateTypeDIE(DIType(Context.getNode()));
|
||||
ContextDIE->addChild(Die);
|
||||
} else if (DIE *ContextDIE = ModuleCU->getDIE(Context.getNode()))
|
||||
ContextDIE->addChild(Die);
|
||||
else
|
||||
ModuleCU->addDie(Die);
|
||||
}
|
||||
|
||||
/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
|
||||
/// given DIType.
|
||||
DIE *DwarfDebug::getOrCreateTypeDIE(DIType Ty) {
|
||||
DIE *TyDIE = ModuleCU->getDIE(Ty.getNode());
|
||||
if (TyDIE)
|
||||
return TyDIE;
|
||||
|
||||
// Create new type.
|
||||
TyDIE = new DIE(dwarf::DW_TAG_base_type);
|
||||
ModuleCU->insertDIE(Ty.getNode(), TyDIE);
|
||||
if (Ty.isBasicType())
|
||||
constructTypeDIE(*TyDIE, DIBasicType(Ty.getNode()));
|
||||
else if (Ty.isCompositeType())
|
||||
constructTypeDIE(*TyDIE, DICompositeType(Ty.getNode()));
|
||||
else {
|
||||
assert(Ty.isDerivedType() && "Unknown kind of DIType");
|
||||
constructTypeDIE(*TyDIE, DIDerivedType(Ty.getNode()));
|
||||
}
|
||||
|
||||
addToContextOwner(TyDIE, Ty.getContext());
|
||||
return TyDIE;
|
||||
}
|
||||
|
||||
/// addType - Add a new type attribute to the specified entity.
|
||||
void DwarfDebug::addType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) {
|
||||
void DwarfDebug::addType(DIE *Entity, DIType Ty) {
|
||||
if (Ty.isNull())
|
||||
return;
|
||||
|
||||
// Check for pre-existence.
|
||||
DIEEntry *Entry = DW_Unit->getDIEEntry(Ty.getNode());
|
||||
DIEEntry *Entry = ModuleCU->getDIEEntry(Ty.getNode());
|
||||
|
||||
// If it exists then use the existing value.
|
||||
if (Entry) {
|
||||
@ -754,36 +790,17 @@ void DwarfDebug::addType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty) {
|
||||
|
||||
// Set up proxy.
|
||||
Entry = createDIEEntry();
|
||||
DW_Unit->insertDIEEntry(Ty.getNode(), Entry);
|
||||
ModuleCU->insertDIEEntry(Ty.getNode(), Entry);
|
||||
|
||||
// Construct type.
|
||||
DIE *Buffer = new DIE(dwarf::DW_TAG_base_type);
|
||||
if (Ty.isBasicType())
|
||||
constructTypeDIE(DW_Unit, *Buffer, DIBasicType(Ty.getNode()));
|
||||
else if (Ty.isCompositeType())
|
||||
constructTypeDIE(DW_Unit, *Buffer, DICompositeType(Ty.getNode()));
|
||||
else {
|
||||
assert(Ty.isDerivedType() && "Unknown kind of DIType");
|
||||
constructTypeDIE(DW_Unit, *Buffer, DIDerivedType(Ty.getNode()));
|
||||
}
|
||||
DIE *Buffer = getOrCreateTypeDIE(Ty);
|
||||
|
||||
// Add debug information entry to entity and appropriate context.
|
||||
DIE *Die = NULL;
|
||||
DIDescriptor Context = Ty.getContext();
|
||||
if (!Context.isNull())
|
||||
Die = DW_Unit->getDIE(Context.getNode());
|
||||
|
||||
if (Die)
|
||||
Die->addChild(Buffer);
|
||||
else
|
||||
DW_Unit->addDie(Buffer);
|
||||
Entry->setEntry(Buffer);
|
||||
Entity->addValue(dwarf::DW_AT_type, dwarf::DW_FORM_ref4, Entry);
|
||||
}
|
||||
|
||||
/// constructTypeDIE - Construct basic type die from DIBasicType.
|
||||
void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
DIBasicType BTy) {
|
||||
void DwarfDebug::constructTypeDIE(DIE &Buffer, DIBasicType BTy) {
|
||||
// Get core information.
|
||||
StringRef Name = BTy.getName();
|
||||
Buffer.setTag(dwarf::DW_TAG_base_type);
|
||||
@ -798,8 +815,7 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
}
|
||||
|
||||
/// constructTypeDIE - Construct derived type die from DIDerivedType.
|
||||
void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
DIDerivedType DTy) {
|
||||
void DwarfDebug::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) {
|
||||
// Get core information.
|
||||
StringRef Name = DTy.getName();
|
||||
uint64_t Size = DTy.getSizeInBits() >> 3;
|
||||
@ -812,7 +828,7 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
|
||||
// Map to main type, void will not have a type.
|
||||
DIType FromTy = DTy.getTypeDerivedFrom();
|
||||
addType(DW_Unit, &Buffer, FromTy);
|
||||
addType(&Buffer, FromTy);
|
||||
|
||||
// Add name if not anonymous or intermediate type.
|
||||
if (!Name.empty())
|
||||
@ -828,8 +844,7 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
}
|
||||
|
||||
/// constructTypeDIE - Construct type DIE from DICompositeType.
|
||||
void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
DICompositeType CTy) {
|
||||
void DwarfDebug::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
|
||||
// Get core information.
|
||||
StringRef Name = CTy.getName();
|
||||
|
||||
@ -840,7 +855,7 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
switch (Tag) {
|
||||
case dwarf::DW_TAG_vector_type:
|
||||
case dwarf::DW_TAG_array_type:
|
||||
constructArrayTypeDIE(DW_Unit, Buffer, &CTy);
|
||||
constructArrayTypeDIE(Buffer, &CTy);
|
||||
break;
|
||||
case dwarf::DW_TAG_enumeration_type: {
|
||||
DIArray Elements = CTy.getTypeArray();
|
||||
@ -850,7 +865,7 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
DIE *ElemDie = NULL;
|
||||
DIEnumerator Enum(Elements.getElement(i).getNode());
|
||||
if (!Enum.isNull()) {
|
||||
ElemDie = constructEnumTypeDIE(DW_Unit, &Enum);
|
||||
ElemDie = constructEnumTypeDIE(&Enum);
|
||||
Buffer.addChild(ElemDie);
|
||||
}
|
||||
}
|
||||
@ -860,7 +875,7 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
// Add return type.
|
||||
DIArray Elements = CTy.getTypeArray();
|
||||
DIDescriptor RTy = Elements.getElement(0);
|
||||
addType(DW_Unit, &Buffer, DIType(RTy.getNode()));
|
||||
addType(&Buffer, DIType(RTy.getNode()));
|
||||
|
||||
// Add prototype flag.
|
||||
addUInt(&Buffer, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1);
|
||||
@ -869,7 +884,7 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) {
|
||||
DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
|
||||
DIDescriptor Ty = Elements.getElement(i);
|
||||
addType(DW_Unit, Arg, DIType(Ty.getNode()));
|
||||
addType(Arg, DIType(Ty.getNode()));
|
||||
Buffer.addChild(Arg);
|
||||
}
|
||||
}
|
||||
@ -891,11 +906,9 @@ void DwarfDebug::constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
continue;
|
||||
DIE *ElemDie = NULL;
|
||||
if (Element.getTag() == dwarf::DW_TAG_subprogram)
|
||||
ElemDie = createSubprogramDIE(DW_Unit,
|
||||
DISubprogram(Element.getNode()));
|
||||
ElemDie = createSubprogramDIE(DISubprogram(Element.getNode()));
|
||||
else
|
||||
ElemDie = createMemberDIE(DW_Unit,
|
||||
DIDerivedType(Element.getNode()));
|
||||
ElemDie = createMemberDIE(DIDerivedType(Element.getNode()));
|
||||
Buffer.addChild(ElemDie);
|
||||
}
|
||||
|
||||
@ -944,33 +957,32 @@ void DwarfDebug::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy){
|
||||
addDIEEntry(DW_Subrange, dwarf::DW_AT_type, dwarf::DW_FORM_ref4, IndexTy);
|
||||
if (L)
|
||||
addSInt(DW_Subrange, dwarf::DW_AT_lower_bound, 0, L);
|
||||
if (H)
|
||||
addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H);
|
||||
addSInt(DW_Subrange, dwarf::DW_AT_upper_bound, 0, H);
|
||||
|
||||
Buffer.addChild(DW_Subrange);
|
||||
}
|
||||
|
||||
/// constructArrayTypeDIE - Construct array type DIE from DICompositeType.
|
||||
void DwarfDebug::constructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
void DwarfDebug::constructArrayTypeDIE(DIE &Buffer,
|
||||
DICompositeType *CTy) {
|
||||
Buffer.setTag(dwarf::DW_TAG_array_type);
|
||||
if (CTy->getTag() == dwarf::DW_TAG_vector_type)
|
||||
addUInt(&Buffer, dwarf::DW_AT_GNU_vector, dwarf::DW_FORM_flag, 1);
|
||||
|
||||
// Emit derived type.
|
||||
addType(DW_Unit, &Buffer, CTy->getTypeDerivedFrom());
|
||||
addType(&Buffer, CTy->getTypeDerivedFrom());
|
||||
DIArray Elements = CTy->getTypeArray();
|
||||
|
||||
// Get an anonymous type for index type.
|
||||
DIE *IdxTy = DW_Unit->getIndexTyDie();
|
||||
DIE *IdxTy = ModuleCU->getIndexTyDie();
|
||||
if (!IdxTy) {
|
||||
// Construct an anonymous type for index type.
|
||||
IdxTy = new DIE(dwarf::DW_TAG_base_type);
|
||||
addUInt(IdxTy, dwarf::DW_AT_byte_size, 0, sizeof(int32_t));
|
||||
addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
|
||||
dwarf::DW_ATE_signed);
|
||||
DW_Unit->addDie(IdxTy);
|
||||
DW_Unit->setIndexTyDie(IdxTy);
|
||||
ModuleCU->addDie(IdxTy);
|
||||
ModuleCU->setIndexTyDie(IdxTy);
|
||||
}
|
||||
|
||||
// Add subranges to array type.
|
||||
@ -982,7 +994,7 @@ void DwarfDebug::constructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
}
|
||||
|
||||
/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
|
||||
DIE *DwarfDebug::constructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) {
|
||||
DIE *DwarfDebug::constructEnumTypeDIE(DIEnumerator *ETy) {
|
||||
DIE *Enumerator = new DIE(dwarf::DW_TAG_enumerator);
|
||||
StringRef Name = ETy->getName();
|
||||
addString(Enumerator, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
|
||||
@ -992,8 +1004,7 @@ DIE *DwarfDebug::constructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy) {
|
||||
}
|
||||
|
||||
/// createGlobalVariableDIE - Create new DIE using GV.
|
||||
DIE *DwarfDebug::createGlobalVariableDIE(CompileUnit *DW_Unit,
|
||||
const DIGlobalVariable &GV) {
|
||||
DIE *DwarfDebug::createGlobalVariableDIE(const DIGlobalVariable &GV) {
|
||||
// If the global variable was optmized out then no need to create debug info
|
||||
// entry.
|
||||
if (!GV.getGlobal()) return NULL;
|
||||
@ -1014,7 +1025,7 @@ DIE *DwarfDebug::createGlobalVariableDIE(CompileUnit *DW_Unit,
|
||||
addString(GVDie, dwarf::DW_AT_MIPS_linkage_name, dwarf::DW_FORM_string,
|
||||
LinkageName);
|
||||
}
|
||||
addType(DW_Unit, GVDie, GV.getType());
|
||||
addType(GVDie, GV.getType());
|
||||
if (!GV.isLocalToUnit())
|
||||
addUInt(GVDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
|
||||
addSourceLine(GVDie, &GV);
|
||||
@ -1030,13 +1041,13 @@ DIE *DwarfDebug::createGlobalVariableDIE(CompileUnit *DW_Unit,
|
||||
}
|
||||
|
||||
/// createMemberDIE - Create new member DIE.
|
||||
DIE *DwarfDebug::createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT){
|
||||
DIE *DwarfDebug::createMemberDIE(const DIDerivedType &DT) {
|
||||
DIE *MemberDie = new DIE(DT.getTag());
|
||||
StringRef Name = DT.getName();
|
||||
if (!Name.empty())
|
||||
addString(MemberDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
|
||||
|
||||
addType(DW_Unit, MemberDie, DT.getTypeDerivedFrom());
|
||||
addType(MemberDie, DT.getTypeDerivedFrom());
|
||||
|
||||
addSourceLine(MemberDie, &DT);
|
||||
|
||||
@ -1073,21 +1084,27 @@ DIE *DwarfDebug::createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT){
|
||||
addBlock(MemberDie, dwarf::DW_AT_data_member_location, 0, MemLocationDie);
|
||||
|
||||
if (DT.isProtected())
|
||||
addUInt(MemberDie, dwarf::DW_AT_accessibility, 0,
|
||||
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag,
|
||||
dwarf::DW_ACCESS_protected);
|
||||
else if (DT.isPrivate())
|
||||
addUInt(MemberDie, dwarf::DW_AT_accessibility, 0,
|
||||
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag,
|
||||
dwarf::DW_ACCESS_private);
|
||||
|
||||
else if (DT.getTag() == dwarf::DW_TAG_inheritance)
|
||||
addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_flag,
|
||||
dwarf::DW_ACCESS_public);
|
||||
if (DT.isVirtual())
|
||||
addUInt(MemberDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag,
|
||||
dwarf::DW_VIRTUALITY_virtual);
|
||||
return MemberDie;
|
||||
}
|
||||
|
||||
/// createSubprogramDIE - Create new DIE using SP.
|
||||
DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit,
|
||||
const DISubprogram &SP,
|
||||
bool IsConstructor,
|
||||
bool IsInlined) {
|
||||
DIE *SPDie = new DIE(dwarf::DW_TAG_subprogram);
|
||||
DIE *DwarfDebug::createSubprogramDIE(const DISubprogram &SP, bool MakeDecl) {
|
||||
DIE *SPDie = ModuleCU->getDIE(SP.getNode());
|
||||
if (SPDie)
|
||||
return SPDie;
|
||||
|
||||
SPDie = new DIE(dwarf::DW_TAG_subprogram);
|
||||
addString(SPDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, SP.getName());
|
||||
|
||||
StringRef LinkageName = SP.getLinkageName();
|
||||
@ -1103,9 +1120,6 @@ DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit,
|
||||
}
|
||||
addSourceLine(SPDie, &SP);
|
||||
|
||||
DICompositeType SPTy = SP.getType();
|
||||
DIArray Args = SPTy.getTypeArray();
|
||||
|
||||
// Add prototyped tag, if C or ObjC.
|
||||
unsigned Lang = SP.getCompileUnit().getLanguage();
|
||||
if (Lang == dwarf::DW_LANG_C99 || Lang == dwarf::DW_LANG_C89 ||
|
||||
@ -1113,98 +1127,56 @@ DIE *DwarfDebug::createSubprogramDIE(CompileUnit *DW_Unit,
|
||||
addUInt(SPDie, dwarf::DW_AT_prototyped, dwarf::DW_FORM_flag, 1);
|
||||
|
||||
// Add Return Type.
|
||||
DICompositeType SPTy = SP.getType();
|
||||
DIArray Args = SPTy.getTypeArray();
|
||||
unsigned SPTag = SPTy.getTag();
|
||||
if (!IsConstructor) {
|
||||
if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type)
|
||||
addType(DW_Unit, SPDie, SPTy);
|
||||
else
|
||||
addType(DW_Unit, SPDie, DIType(Args.getElement(0).getNode()));
|
||||
|
||||
if (Args.isNull() || SPTag != dwarf::DW_TAG_subroutine_type)
|
||||
addType(SPDie, SPTy);
|
||||
else
|
||||
addType(SPDie, DIType(Args.getElement(0).getNode()));
|
||||
|
||||
unsigned VK = SP.getVirtuality();
|
||||
if (VK) {
|
||||
addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_flag, VK);
|
||||
DIEBlock *Block = new DIEBlock();
|
||||
addUInt(Block, 0, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
|
||||
addUInt(Block, 0, dwarf::DW_FORM_data1, SP.getVirtualIndex());
|
||||
addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, 0, Block);
|
||||
ContainingTypeMap.insert(std::make_pair(SPDie, WeakVH(SP.getContainingType().getNode())));
|
||||
}
|
||||
|
||||
if (!SP.isDefinition()) {
|
||||
if (MakeDecl || !SP.isDefinition()) {
|
||||
addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
|
||||
|
||||
// Add arguments. Do not add arguments for subprogram definition. They will
|
||||
// be handled through RecordVariable.
|
||||
// be handled while processing variables.
|
||||
DICompositeType SPTy = SP.getType();
|
||||
DIArray Args = SPTy.getTypeArray();
|
||||
unsigned SPTag = SPTy.getTag();
|
||||
|
||||
if (SPTag == dwarf::DW_TAG_subroutine_type)
|
||||
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
|
||||
DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
|
||||
addType(DW_Unit, Arg, DIType(Args.getElement(i).getNode()));
|
||||
addType(Arg, DIType(Args.getElement(i).getNode()));
|
||||
addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ??
|
||||
SPDie->addChild(Arg);
|
||||
}
|
||||
}
|
||||
|
||||
// DW_TAG_inlined_subroutine may refer to this DIE.
|
||||
DW_Unit->insertDIE(SP.getNode(), SPDie);
|
||||
ModuleCU->insertDIE(SP.getNode(), SPDie);
|
||||
return SPDie;
|
||||
}
|
||||
|
||||
/// findCompileUnit - Get the compile unit for the given descriptor.
|
||||
///
|
||||
CompileUnit &DwarfDebug::findCompileUnit(DICompileUnit Unit) const {
|
||||
CompileUnit *DwarfDebug::findCompileUnit(DICompileUnit Unit) {
|
||||
DenseMap<Value *, CompileUnit *>::const_iterator I =
|
||||
CompileUnitMap.find(Unit.getNode());
|
||||
assert(I != CompileUnitMap.end() && "Missing compile unit.");
|
||||
return *I->second;
|
||||
}
|
||||
|
||||
/// createDbgScopeVariable - Create a new scope variable.
|
||||
///
|
||||
DIE *DwarfDebug::createDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit) {
|
||||
// Get the descriptor.
|
||||
const DIVariable &VD = DV->getVariable();
|
||||
StringRef Name = VD.getName();
|
||||
if (Name.empty())
|
||||
return NULL;
|
||||
|
||||
// Translate tag to proper Dwarf tag. The result variable is dropped for
|
||||
// now.
|
||||
unsigned Tag;
|
||||
switch (VD.getTag()) {
|
||||
case dwarf::DW_TAG_return_variable:
|
||||
return NULL;
|
||||
case dwarf::DW_TAG_arg_variable:
|
||||
Tag = dwarf::DW_TAG_formal_parameter;
|
||||
break;
|
||||
case dwarf::DW_TAG_auto_variable: // fall thru
|
||||
default:
|
||||
Tag = dwarf::DW_TAG_variable;
|
||||
break;
|
||||
}
|
||||
|
||||
// Define variable debug information entry.
|
||||
DIE *VariableDie = new DIE(Tag);
|
||||
addString(VariableDie, dwarf::DW_AT_name, dwarf::DW_FORM_string, Name);
|
||||
|
||||
// Add source line info if available.
|
||||
addSourceLine(VariableDie, &VD);
|
||||
|
||||
// Add variable type.
|
||||
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
|
||||
// addresses instead.
|
||||
if (VD.isBlockByrefVariable())
|
||||
addType(Unit, VariableDie, getBlockByrefType(VD.getType(), Name));
|
||||
else
|
||||
addType(Unit, VariableDie, VD.getType());
|
||||
|
||||
// Add variable address.
|
||||
// Variables for abstract instances of inlined functions don't get a
|
||||
// location.
|
||||
MachineLocation Location;
|
||||
unsigned FrameReg;
|
||||
int Offset = RI->getFrameIndexReference(*MF, DV->getFrameIndex(), FrameReg);
|
||||
Location.set(FrameReg, Offset);
|
||||
|
||||
|
||||
if (VD.hasComplexAddress())
|
||||
addComplexAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
|
||||
else if (VD.isBlockByrefVariable())
|
||||
addBlockByrefAddress(DV, VariableDie, dwarf::DW_AT_location, Location);
|
||||
else
|
||||
addAddress(VariableDie, dwarf::DW_AT_location, Location);
|
||||
|
||||
return VariableDie;
|
||||
if (I == CompileUnitMap.end())
|
||||
return constructCompileUnit(Unit.getNode());
|
||||
return I->second;
|
||||
}
|
||||
|
||||
/// getUpdatedDbgScope - Find or create DbgScope assicated with the instruction.
|
||||
@ -1295,6 +1267,28 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) {
|
||||
|
||||
DIE *SPDie = ModuleCU->getDIE(SPNode);
|
||||
assert (SPDie && "Unable to find subprogram DIE!");
|
||||
DISubprogram SP(SPNode);
|
||||
if (SP.isDefinition() && !SP.getContext().isCompileUnit()) {
|
||||
addUInt(SPDie, dwarf::DW_AT_declaration, dwarf::DW_FORM_flag, 1);
|
||||
// Add arguments.
|
||||
DICompositeType SPTy = SP.getType();
|
||||
DIArray Args = SPTy.getTypeArray();
|
||||
unsigned SPTag = SPTy.getTag();
|
||||
if (SPTag == dwarf::DW_TAG_subroutine_type)
|
||||
for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
|
||||
DIE *Arg = new DIE(dwarf::DW_TAG_formal_parameter);
|
||||
addType(Arg, DIType(Args.getElement(i).getNode()));
|
||||
addUInt(Arg, dwarf::DW_AT_artificial, dwarf::DW_FORM_flag, 1); // ??
|
||||
SPDie->addChild(Arg);
|
||||
}
|
||||
DIE *SPDeclDie = SPDie;
|
||||
SPDie = new DIE(dwarf::DW_TAG_subprogram);
|
||||
addDIEEntry(SPDie, dwarf::DW_AT_specification, dwarf::DW_FORM_ref4,
|
||||
SPDeclDie);
|
||||
|
||||
ModuleCU->addDie(SPDie);
|
||||
}
|
||||
|
||||
addLabel(SPDie, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
|
||||
DWLabel("func_begin", SubprogramCount));
|
||||
addLabel(SPDie, dwarf::DW_AT_high_pc, dwarf::DW_FORM_addr,
|
||||
@ -1305,19 +1299,6 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(MDNode *SPNode) {
|
||||
if (!DISubprogram(SPNode).isLocalToUnit())
|
||||
addUInt(SPDie, dwarf::DW_AT_external, dwarf::DW_FORM_flag, 1);
|
||||
|
||||
// If there are global variables at this scope then add their dies.
|
||||
for (SmallVector<WeakVH, 4>::iterator SGI = ScopedGVs.begin(),
|
||||
SGE = ScopedGVs.end(); SGI != SGE; ++SGI) {
|
||||
MDNode *N = dyn_cast_or_null<MDNode>(*SGI);
|
||||
if (!N) continue;
|
||||
DIGlobalVariable GV(N);
|
||||
if (GV.getContext().getNode() == SPNode) {
|
||||
DIE *ScopedGVDie = createGlobalVariableDIE(ModuleCU, GV);
|
||||
if (ScopedGVDie)
|
||||
SPDie->addChild(ScopedGVDie);
|
||||
}
|
||||
}
|
||||
|
||||
return SPDie;
|
||||
}
|
||||
|
||||
@ -1401,8 +1382,7 @@ DIE *DwarfDebug::constructInlinedScopeDIE(DbgScope *Scope) {
|
||||
|
||||
|
||||
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
|
||||
DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV,
|
||||
DbgScope *Scope, CompileUnit *Unit) {
|
||||
DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV, DbgScope *Scope) {
|
||||
// Get the descriptor.
|
||||
const DIVariable &VD = DV->getVariable();
|
||||
StringRef Name = VD.getName();
|
||||
@ -1451,9 +1431,9 @@ DIE *DwarfDebug::constructVariableDIE(DbgVariable *DV,
|
||||
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
|
||||
// addresses instead.
|
||||
if (VD.isBlockByrefVariable())
|
||||
addType(Unit, VariableDie, getBlockByrefType(VD.getType(), Name));
|
||||
addType(VariableDie, getBlockByrefType(VD.getType(), Name));
|
||||
else
|
||||
addType(Unit, VariableDie, VD.getType());
|
||||
addType(VariableDie, VD.getType());
|
||||
}
|
||||
|
||||
// Add variable address.
|
||||
@ -1522,7 +1502,7 @@ DIE *DwarfDebug::constructScopeDIE(DbgScope *Scope) {
|
||||
// Add variables to scope.
|
||||
SmallVector<DbgVariable *, 8> &Variables = Scope->getVariables();
|
||||
for (unsigned i = 0, N = Variables.size(); i < N; ++i) {
|
||||
DIE *VariableDIE = constructVariableDIE(Variables[i], Scope, ModuleCU);
|
||||
DIE *VariableDIE = constructVariableDIE(Variables[i], Scope);
|
||||
if (VariableDIE)
|
||||
ScopeDIE->addChild(VariableDIE);
|
||||
}
|
||||
@ -1579,7 +1559,7 @@ unsigned DwarfDebug::GetOrCreateSourceID(StringRef DirName, StringRef FileName)
|
||||
return SrcId;
|
||||
}
|
||||
|
||||
void DwarfDebug::constructCompileUnit(MDNode *N) {
|
||||
CompileUnit *DwarfDebug::constructCompileUnit(MDNode *N) {
|
||||
DICompileUnit DIUnit(N);
|
||||
StringRef FN = DIUnit.getFilename();
|
||||
StringRef Dir = DIUnit.getDirectory();
|
||||
@ -1618,6 +1598,7 @@ void DwarfDebug::constructCompileUnit(MDNode *N) {
|
||||
|
||||
CompileUnitMap[DIUnit.getNode()] = Unit;
|
||||
CompileUnits.push_back(Unit);
|
||||
return Unit;
|
||||
}
|
||||
|
||||
void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
|
||||
@ -1631,14 +1612,16 @@ void DwarfDebug::constructGlobalVariableDIE(MDNode *N) {
|
||||
if (ModuleCU->getDIE(DI_GV.getNode()))
|
||||
return;
|
||||
|
||||
DIE *VariableDie = createGlobalVariableDIE(ModuleCU, DI_GV);
|
||||
DIE *VariableDie = createGlobalVariableDIE(DI_GV);
|
||||
if (!VariableDie)
|
||||
return;
|
||||
|
||||
// Add to map.
|
||||
ModuleCU->insertDIE(N, VariableDie);
|
||||
|
||||
// Add to context owner.
|
||||
ModuleCU->getCUDie()->addChild(VariableDie);
|
||||
|
||||
addToContextOwner(VariableDie, DI_GV.getContext());
|
||||
|
||||
// Expose as global. FIXME - need to check external flag.
|
||||
ModuleCU->addGlobal(DI_GV.getName(), VariableDie);
|
||||
|
||||
@ -1663,13 +1646,15 @@ void DwarfDebug::constructSubprogramDIE(MDNode *N) {
|
||||
// class type.
|
||||
return;
|
||||
|
||||
DIE *SubprogramDie = createSubprogramDIE(ModuleCU, SP);
|
||||
DIE *SubprogramDie = createSubprogramDIE(SP);
|
||||
|
||||
// Add to map.
|
||||
ModuleCU->insertDIE(N, SubprogramDie);
|
||||
|
||||
// Add to context owner.
|
||||
ModuleCU->getCUDie()->addChild(SubprogramDie);
|
||||
if (SP.getContext().getNode() == SP.getCompileUnit().getNode())
|
||||
if (TopLevelDIEs.insert(SubprogramDie))
|
||||
TopLevelDIEsVector.push_back(SubprogramDie);
|
||||
|
||||
// Expose as global.
|
||||
ModuleCU->addGlobal(SP.getName(), SubprogramDie);
|
||||
@ -1709,21 +1694,16 @@ void DwarfDebug::beginModule(Module *M, MachineModuleInfo *mmi) {
|
||||
if (!ModuleCU)
|
||||
ModuleCU = CompileUnits[0];
|
||||
|
||||
// Create DIEs for each of the externally visible global variables.
|
||||
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
|
||||
E = DbgFinder.global_variable_end(); I != E; ++I) {
|
||||
DIGlobalVariable GV(*I);
|
||||
if (GV.getContext().getNode() != GV.getCompileUnit().getNode())
|
||||
ScopedGVs.push_back(*I);
|
||||
else
|
||||
constructGlobalVariableDIE(*I);
|
||||
}
|
||||
|
||||
// Create DIEs for each subprogram.
|
||||
for (DebugInfoFinder::iterator I = DbgFinder.subprogram_begin(),
|
||||
E = DbgFinder.subprogram_end(); I != E; ++I)
|
||||
constructSubprogramDIE(*I);
|
||||
|
||||
// Create DIEs for each global variable.
|
||||
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
|
||||
E = DbgFinder.global_variable_end(); I != E; ++I)
|
||||
constructGlobalVariableDIE(*I);
|
||||
|
||||
MMI = mmi;
|
||||
shouldEmit = true;
|
||||
MMI->setDebugInfoAvailability(true);
|
||||
@ -1770,6 +1750,22 @@ void DwarfDebug::endModule() {
|
||||
addUInt(ISP, dwarf::DW_AT_inline, 0, dwarf::DW_INL_inlined);
|
||||
}
|
||||
|
||||
// Insert top level DIEs.
|
||||
for (SmallVector<DIE *, 4>::iterator TI = TopLevelDIEsVector.begin(),
|
||||
TE = TopLevelDIEsVector.end(); TI != TE; ++TI)
|
||||
ModuleCU->getCUDie()->addChild(*TI);
|
||||
|
||||
for (DenseMap<DIE *, WeakVH>::iterator CI = ContainingTypeMap.begin(),
|
||||
CE = ContainingTypeMap.end(); CI != CE; ++CI) {
|
||||
DIE *SPDie = CI->first;
|
||||
MDNode *N = dyn_cast_or_null<MDNode>(CI->second);
|
||||
if (!N) continue;
|
||||
DIE *NDie = ModuleCU->getDIE(N);
|
||||
if (!NDie) continue;
|
||||
addDIEEntry(SPDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
|
||||
addDIEEntry(NDie, dwarf::DW_AT_containing_type, dwarf::DW_FORM_ref4, NDie);
|
||||
}
|
||||
|
||||
// Standard sections final addresses.
|
||||
Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering().getTextSection());
|
||||
EmitLabel("text_end", 0);
|
||||
@ -1898,6 +1894,7 @@ void DwarfDebug::endScope(const MachineInstr *MI) {
|
||||
|
||||
unsigned Label = MMI->NextLabelID();
|
||||
Asm->printLabel(Label);
|
||||
O << '\n';
|
||||
|
||||
SmallVector<DbgScope *, 2> &SD = I->second;
|
||||
for (SmallVector<DbgScope *, 2>::iterator SDI = SD.begin(), SDE = SD.end();
|
||||
@ -2092,17 +2089,15 @@ void DwarfDebug::endFunction(MachineFunction *MF) {
|
||||
MMI->getFrameMoves()));
|
||||
|
||||
// Clear debug info
|
||||
if (CurrentFnDbgScope) {
|
||||
CurrentFnDbgScope = NULL;
|
||||
DbgScopeMap.clear();
|
||||
DbgScopeBeginMap.clear();
|
||||
DbgScopeEndMap.clear();
|
||||
ConcreteScopes.clear();
|
||||
AbstractScopesList.clear();
|
||||
}
|
||||
CurrentFnDbgScope = NULL;
|
||||
DbgScopeMap.clear();
|
||||
DbgScopeBeginMap.clear();
|
||||
DbgScopeEndMap.clear();
|
||||
ConcreteScopes.clear();
|
||||
AbstractScopesList.clear();
|
||||
|
||||
Lines.clear();
|
||||
|
||||
|
||||
if (TimePassesIsEnabled)
|
||||
DebugTimer->stopTimer();
|
||||
}
|
||||
@ -2337,13 +2332,16 @@ void DwarfDebug::emitDIE(DIE *Die) {
|
||||
}
|
||||
}
|
||||
|
||||
/// emitDebugInfo / emitDebugInfoPerCU - Emit the debug info section.
|
||||
/// emitDebugInfo - Emit the debug info section.
|
||||
///
|
||||
void DwarfDebug::emitDebugInfoPerCU(CompileUnit *Unit) {
|
||||
DIE *Die = Unit->getCUDie();
|
||||
void DwarfDebug::emitDebugInfo() {
|
||||
// Start debug info section.
|
||||
Asm->OutStreamer.SwitchSection(
|
||||
Asm->getObjFileLowering().getDwarfInfoSection());
|
||||
DIE *Die = ModuleCU->getCUDie();
|
||||
|
||||
// Emit the compile units header.
|
||||
EmitLabel("info_begin", Unit->getID());
|
||||
EmitLabel("info_begin", ModuleCU->getID());
|
||||
|
||||
// Emit size of content not including length itself
|
||||
unsigned ContentSize = Die->getSize() +
|
||||
@ -2364,17 +2362,10 @@ void DwarfDebug::emitDebugInfoPerCU(CompileUnit *Unit) {
|
||||
Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
|
||||
Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
|
||||
Asm->EmitInt8(0); Asm->EOL("Extra Pad For GDB");
|
||||
EmitLabel("info_end", Unit->getID());
|
||||
EmitLabel("info_end", ModuleCU->getID());
|
||||
|
||||
Asm->EOL();
|
||||
}
|
||||
|
||||
void DwarfDebug::emitDebugInfo() {
|
||||
// Start debug info section.
|
||||
Asm->OutStreamer.SwitchSection(
|
||||
Asm->getObjFileLowering().getDwarfInfoSection());
|
||||
|
||||
emitDebugInfoPerCU(ModuleCU);
|
||||
}
|
||||
|
||||
/// emitAbbreviations - Emit the abbreviation section.
|
||||
@ -2534,9 +2525,9 @@ void DwarfDebug::emitDebugLines() {
|
||||
std::pair<unsigned, unsigned> SourceID =
|
||||
getSourceDirectoryAndFileIds(LineInfo.getSourceID());
|
||||
O << '\t' << MAI->getCommentString() << ' '
|
||||
<< getSourceDirectoryName(SourceID.first) << ' '
|
||||
<< getSourceDirectoryName(SourceID.first) << '/'
|
||||
<< getSourceFileName(SourceID.second)
|
||||
<<" :" << utostr_32(LineInfo.getLine()) << '\n';
|
||||
<< ':' << utostr_32(LineInfo.getLine()) << '\n';
|
||||
}
|
||||
|
||||
// Define the line address.
|
||||
@ -2672,24 +2663,30 @@ DwarfDebug::emitFunctionDebugFrame(const FunctionDebugFrameInfo&DebugFrameInfo){
|
||||
Asm->EOL();
|
||||
}
|
||||
|
||||
void DwarfDebug::emitDebugPubNamesPerCU(CompileUnit *Unit) {
|
||||
EmitDifference("pubnames_end", Unit->getID(),
|
||||
"pubnames_begin", Unit->getID(), true);
|
||||
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
|
||||
///
|
||||
void DwarfDebug::emitDebugPubNames() {
|
||||
// Start the dwarf pubnames section.
|
||||
Asm->OutStreamer.SwitchSection(
|
||||
Asm->getObjFileLowering().getDwarfPubNamesSection());
|
||||
|
||||
EmitDifference("pubnames_end", ModuleCU->getID(),
|
||||
"pubnames_begin", ModuleCU->getID(), true);
|
||||
Asm->EOL("Length of Public Names Info");
|
||||
|
||||
EmitLabel("pubnames_begin", Unit->getID());
|
||||
EmitLabel("pubnames_begin", ModuleCU->getID());
|
||||
|
||||
Asm->EmitInt16(dwarf::DWARF_VERSION); Asm->EOL("DWARF Version");
|
||||
|
||||
EmitSectionOffset("info_begin", "section_info",
|
||||
Unit->getID(), 0, true, false);
|
||||
ModuleCU->getID(), 0, true, false);
|
||||
Asm->EOL("Offset of Compilation Unit Info");
|
||||
|
||||
EmitDifference("info_end", Unit->getID(), "info_begin", Unit->getID(),
|
||||
EmitDifference("info_end", ModuleCU->getID(), "info_begin", ModuleCU->getID(),
|
||||
true);
|
||||
Asm->EOL("Compilation Unit Length");
|
||||
|
||||
const StringMap<DIE*> &Globals = Unit->getGlobals();
|
||||
const StringMap<DIE*> &Globals = ModuleCU->getGlobals();
|
||||
for (StringMap<DIE*>::const_iterator
|
||||
GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
|
||||
const char *Name = GI->getKeyData();
|
||||
@ -2700,21 +2697,11 @@ void DwarfDebug::emitDebugPubNamesPerCU(CompileUnit *Unit) {
|
||||
}
|
||||
|
||||
Asm->EmitInt32(0); Asm->EOL("End Mark");
|
||||
EmitLabel("pubnames_end", Unit->getID());
|
||||
EmitLabel("pubnames_end", ModuleCU->getID());
|
||||
|
||||
Asm->EOL();
|
||||
}
|
||||
|
||||
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
|
||||
///
|
||||
void DwarfDebug::emitDebugPubNames() {
|
||||
// Start the dwarf pubnames section.
|
||||
Asm->OutStreamer.SwitchSection(
|
||||
Asm->getObjFileLowering().getDwarfPubNamesSection());
|
||||
|
||||
emitDebugPubNamesPerCU(ModuleCU);
|
||||
}
|
||||
|
||||
void DwarfDebug::emitDebugPubTypes() {
|
||||
// Start the dwarf pubnames section.
|
||||
Asm->OutStreamer.SwitchSection(
|
||||
|
@ -154,12 +154,14 @@ class DwarfDebug : public Dwarf {
|
||||
/// (at the end of the module) as DW_AT_inline.
|
||||
SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs;
|
||||
|
||||
DenseMap<DIE *, WeakVH> ContainingTypeMap;
|
||||
|
||||
/// AbstractSubprogramDIEs - Collection of abstruct subprogram DIEs.
|
||||
SmallPtrSet<DIE *, 4> AbstractSubprogramDIEs;
|
||||
|
||||
/// ScopedGVs - Tracks global variables that are not at file scope.
|
||||
/// For example void f() { static int b = 42; }
|
||||
SmallVector<WeakVH, 4> ScopedGVs;
|
||||
/// TopLevelDIEs - Collection of top level DIEs.
|
||||
SmallPtrSet<DIE *, 4> TopLevelDIEs;
|
||||
SmallVector<DIE *, 4> TopLevelDIEsVector;
|
||||
|
||||
typedef SmallVector<DbgScope *, 2> ScopeVector;
|
||||
typedef DenseMap<const MachineInstr *, ScopeVector>
|
||||
@ -307,53 +309,52 @@ class DwarfDebug : public Dwarf {
|
||||
void addBlockByrefAddress(DbgVariable *&DV, DIE *Die, unsigned Attribute,
|
||||
const MachineLocation &Location);
|
||||
|
||||
/// addToContextOwner - Add Die into the list of its context owner's children.
|
||||
void addToContextOwner(DIE *Die, DIDescriptor Context);
|
||||
|
||||
/// addType - Add a new type attribute to the specified entity.
|
||||
void addType(CompileUnit *DW_Unit, DIE *Entity, DIType Ty);
|
||||
void addType(DIE *Entity, DIType Ty);
|
||||
|
||||
/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
|
||||
/// given DIType.
|
||||
DIE *getOrCreateTypeDIE(DIType Ty);
|
||||
|
||||
void addPubTypes(DISubprogram SP);
|
||||
|
||||
/// constructTypeDIE - Construct basic type die from DIBasicType.
|
||||
void constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
void constructTypeDIE(DIE &Buffer,
|
||||
DIBasicType BTy);
|
||||
|
||||
/// constructTypeDIE - Construct derived type die from DIDerivedType.
|
||||
void constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
void constructTypeDIE(DIE &Buffer,
|
||||
DIDerivedType DTy);
|
||||
|
||||
/// constructTypeDIE - Construct type DIE from DICompositeType.
|
||||
void constructTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
void constructTypeDIE(DIE &Buffer,
|
||||
DICompositeType CTy);
|
||||
|
||||
/// constructSubrangeDIE - Construct subrange DIE from DISubrange.
|
||||
void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy);
|
||||
|
||||
/// constructArrayTypeDIE - Construct array type DIE from DICompositeType.
|
||||
void constructArrayTypeDIE(CompileUnit *DW_Unit, DIE &Buffer,
|
||||
void constructArrayTypeDIE(DIE &Buffer,
|
||||
DICompositeType *CTy);
|
||||
|
||||
/// constructEnumTypeDIE - Construct enum type DIE from DIEnumerator.
|
||||
DIE *constructEnumTypeDIE(CompileUnit *DW_Unit, DIEnumerator *ETy);
|
||||
DIE *constructEnumTypeDIE(DIEnumerator *ETy);
|
||||
|
||||
/// createGlobalVariableDIE - Create new DIE using GV.
|
||||
DIE *createGlobalVariableDIE(CompileUnit *DW_Unit,
|
||||
const DIGlobalVariable &GV);
|
||||
DIE *createGlobalVariableDIE(const DIGlobalVariable &GV);
|
||||
|
||||
/// createMemberDIE - Create new member DIE.
|
||||
DIE *createMemberDIE(CompileUnit *DW_Unit, const DIDerivedType &DT);
|
||||
DIE *createMemberDIE(const DIDerivedType &DT);
|
||||
|
||||
/// createSubprogramDIE - Create new DIE using SP.
|
||||
DIE *createSubprogramDIE(CompileUnit *DW_Unit,
|
||||
const DISubprogram &SP,
|
||||
bool IsConstructor = false,
|
||||
bool IsInlined = false);
|
||||
DIE *createSubprogramDIE(const DISubprogram &SP, bool MakeDecl = false);
|
||||
|
||||
/// findCompileUnit - Get the compile unit for the given descriptor.
|
||||
///
|
||||
CompileUnit &findCompileUnit(DICompileUnit Unit) const;
|
||||
|
||||
/// createDbgScopeVariable - Create a new scope variable.
|
||||
///
|
||||
DIE *createDbgScopeVariable(DbgVariable *DV, CompileUnit *Unit);
|
||||
CompileUnit *findCompileUnit(DICompileUnit Unit);
|
||||
|
||||
/// getUpdatedDbgScope - Find or create DbgScope assicated with
|
||||
/// the instruction. Initialize scope and update scope hierarchy.
|
||||
@ -384,7 +385,7 @@ class DwarfDebug : public Dwarf {
|
||||
DIE *constructInlinedScopeDIE(DbgScope *Scope);
|
||||
|
||||
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
|
||||
DIE *constructVariableDIE(DbgVariable *DV, DbgScope *S, CompileUnit *Unit);
|
||||
DIE *constructVariableDIE(DbgVariable *DV, DbgScope *S);
|
||||
|
||||
/// constructScopeDIE - Construct a DIE for this scope.
|
||||
DIE *constructScopeDIE(DbgScope *Scope);
|
||||
@ -405,10 +406,8 @@ class DwarfDebug : public Dwarf {
|
||||
///
|
||||
void computeSizeAndOffsets();
|
||||
|
||||
/// EmitDebugInfo / emitDebugInfoPerCU - Emit the debug info section.
|
||||
/// EmitDebugInfo - Emit the debug info section.
|
||||
///
|
||||
void emitDebugInfoPerCU(CompileUnit *Unit);
|
||||
|
||||
void emitDebugInfo();
|
||||
|
||||
/// emitAbbreviations - Emit the abbreviation section.
|
||||
@ -432,8 +431,6 @@ class DwarfDebug : public Dwarf {
|
||||
/// section.
|
||||
void emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo);
|
||||
|
||||
void emitDebugPubNamesPerCU(CompileUnit *Unit);
|
||||
|
||||
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
|
||||
///
|
||||
void emitDebugPubNames();
|
||||
@ -488,7 +485,7 @@ class DwarfDebug : public Dwarf {
|
||||
/// as well.
|
||||
unsigned GetOrCreateSourceID(StringRef DirName, StringRef FileName);
|
||||
|
||||
void constructCompileUnit(MDNode *N);
|
||||
CompileUnit *constructCompileUnit(MDNode *N);
|
||||
|
||||
void constructGlobalVariableDIE(MDNode *N);
|
||||
|
||||
|
@ -292,14 +292,13 @@ void DwarfException::EmitFDE(const FunctionEHFrameInfo &EHFrameInfo) {
|
||||
Asm->EmitULEB128Bytes(is4Byte ? 4 : 8);
|
||||
Asm->EOL("Augmentation size");
|
||||
|
||||
// We force 32-bits here because we've encoded our LSDA in the CIE with
|
||||
// `dwarf::DW_EH_PE_sdata4'. And the CIE and FDE should agree.
|
||||
if (EHFrameInfo.hasLandingPads)
|
||||
EmitReference("exception", EHFrameInfo.Number, true, false);
|
||||
else {
|
||||
if (is4Byte)
|
||||
Asm->EmitInt32((int)0);
|
||||
else
|
||||
Asm->EmitInt64((int)0);
|
||||
}
|
||||
EmitReference("exception", EHFrameInfo.Number, true, true);
|
||||
else
|
||||
Asm->EmitInt32((int)0);
|
||||
|
||||
Asm->EOL("Language Specific Data Area");
|
||||
} else {
|
||||
Asm->EmitULEB128Bytes(0);
|
||||
|
@ -119,7 +119,6 @@ class DwarfException : public Dwarf {
|
||||
static inline unsigned getTombstoneKey() { return -2U; }
|
||||
static unsigned getHashValue(const unsigned &Key) { return Key; }
|
||||
static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; }
|
||||
static bool isPod() { return true; }
|
||||
};
|
||||
|
||||
/// PadRange - Structure holding a try-range and the associated landing pad.
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user