Update LLVM to r99115.
This commit is contained in:
parent
0f448b8416
commit
2f2afc1aae
@ -217,7 +217,9 @@ if( MSVC )
|
||||
# List of valid CRTs for MSVC
|
||||
set(MSVC_CRT
|
||||
MD
|
||||
MDd)
|
||||
MDd
|
||||
MT
|
||||
MTd)
|
||||
|
||||
set(LLVM_USE_CRT "" CACHE STRING "Specify VC++ CRT to use for debug/release configurations.")
|
||||
add_llvm_definitions( -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS )
|
||||
|
@ -578,8 +578,6 @@ endif
|
||||
ifeq ($(TARGET_OS),Darwin)
|
||||
ifneq ($(ARCH),ARM)
|
||||
TargetCommonOpts += -mmacosx-version-min=$(DARWIN_VERSION)
|
||||
else
|
||||
TargetCommonOpts += -marm
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -31,12 +31,12 @@ dnl===
|
||||
dnl===-----------------------------------------------------------------------===
|
||||
dnl Initialize autoconf and define the package name, version number and
|
||||
dnl email address for reporting bugs.
|
||||
AC_INIT([[llvm]],[[2.7svn]],[llvmbugs@cs.uiuc.edu])
|
||||
AC_INIT([[llvm]],[[2.8svn]],[llvmbugs@cs.uiuc.edu])
|
||||
|
||||
dnl Provide a copyright substitution and ensure the copyright notice is included
|
||||
dnl in the output of --version option of the generated configure script.
|
||||
AC_SUBST(LLVM_COPYRIGHT,["Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign."])
|
||||
AC_COPYRIGHT([Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign.])
|
||||
AC_SUBST(LLVM_COPYRIGHT,["Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign."])
|
||||
AC_COPYRIGHT([Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign.])
|
||||
|
||||
dnl Indicate that we require autoconf 2.59 or later. Ths is needed because we
|
||||
dnl use some autoconf macros only available in 2.59.
|
||||
@ -62,6 +62,41 @@ dnl Configure all of the projects present in our source tree. While we could
|
||||
dnl just AC_CONFIG_SUBDIRS on the set of directories in projects that have a
|
||||
dnl configure script, that usage of the AC_CONFIG_SUBDIRS macro is deprecated.
|
||||
dnl Instead we match on the known projects.
|
||||
|
||||
dnl
|
||||
dnl One tricky part of doing this is that some projects depend upon other
|
||||
dnl projects. For example, several projects rely upon the LLVM test suite.
|
||||
dnl We want to configure those projects first so that their object trees are
|
||||
dnl created before running the configure scripts of projects that depend upon
|
||||
dnl them.
|
||||
dnl
|
||||
|
||||
dnl Several projects use llvm-gcc, so configure that first
|
||||
if test -d ${srcdir}/projects/llvm-gcc ; then
|
||||
AC_CONFIG_SUBDIRS([projects/llvm-gcc])
|
||||
fi
|
||||
|
||||
dnl Several projects use the LLVM test suite, so configure it next.
|
||||
if test -d ${srcdir}/projects/test-suite ; then
|
||||
AC_CONFIG_SUBDIRS([projects/test-suite])
|
||||
fi
|
||||
|
||||
dnl llvm-test is the old name of the test-suite, kept here for backwards
|
||||
dnl compatibility
|
||||
if test -d ${srcdir}/projects/llvm-test ; then
|
||||
AC_CONFIG_SUBDIRS([projects/llvm-test])
|
||||
fi
|
||||
|
||||
dnl Some projects use poolalloc; configure that next
|
||||
if test -d ${srcdir}/projects/poolalloc ; then
|
||||
AC_CONFIG_SUBDIRS([projects/poolalloc])
|
||||
fi
|
||||
|
||||
if test -d ${srcdir}/projects/llvm-poolalloc ; then
|
||||
AC_CONFIG_SUBDIRS([projects/llvm-poolalloc])
|
||||
fi
|
||||
|
||||
dnl Check for all other projects
|
||||
for i in `ls ${srcdir}/projects`
|
||||
do
|
||||
if test -d ${srcdir}/projects/${i} ; then
|
||||
@ -70,16 +105,9 @@ do
|
||||
sample) AC_CONFIG_SUBDIRS([projects/sample]) ;;
|
||||
privbracket) AC_CONFIG_SUBDIRS([projects/privbracket]) ;;
|
||||
llvm-stacker) AC_CONFIG_SUBDIRS([projects/llvm-stacker]) ;;
|
||||
# llvm-test is the old name of the test-suite, kept here for backwards
|
||||
# compatibility
|
||||
llvm-test) AC_CONFIG_SUBDIRS([projects/llvm-test]) ;;
|
||||
test-suite) AC_CONFIG_SUBDIRS([projects/test-suite]) ;;
|
||||
llvm-reopt) AC_CONFIG_SUBDIRS([projects/llvm-reopt]);;
|
||||
llvm-gcc) AC_CONFIG_SUBDIRS([projects/llvm-gcc]) ;;
|
||||
llvm-java) AC_CONFIG_SUBDIRS([projects/llvm-java]) ;;
|
||||
llvm-tv) AC_CONFIG_SUBDIRS([projects/llvm-tv]) ;;
|
||||
llvm-poolalloc) AC_CONFIG_SUBDIRS([projects/llvm-poolalloc]) ;;
|
||||
poolalloc) AC_CONFIG_SUBDIRS([projects/poolalloc]) ;;
|
||||
safecode) AC_CONFIG_SUBDIRS([projects/safecode]) ;;
|
||||
llvm-kernel) AC_CONFIG_SUBDIRS([projects/llvm-kernel]) ;;
|
||||
*)
|
||||
|
77
configure
vendored
77
configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.60 for llvm 2.7svn.
|
||||
# Generated by GNU Autoconf 2.60 for llvm 2.8svn.
|
||||
#
|
||||
# Report bugs to <llvmbugs@cs.uiuc.edu>.
|
||||
#
|
||||
@ -9,7 +9,7 @@
|
||||
# This configure script is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy, distribute and modify it.
|
||||
#
|
||||
# Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign.
|
||||
# Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign.
|
||||
## --------------------- ##
|
||||
## M4sh Initialization. ##
|
||||
## --------------------- ##
|
||||
@ -561,8 +561,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='llvm'
|
||||
PACKAGE_TARNAME='-llvm-'
|
||||
PACKAGE_VERSION='2.7svn'
|
||||
PACKAGE_STRING='llvm 2.7svn'
|
||||
PACKAGE_VERSION='2.8svn'
|
||||
PACKAGE_STRING='llvm 2.8svn'
|
||||
PACKAGE_BUGREPORT='llvmbugs@cs.uiuc.edu'
|
||||
|
||||
ac_unique_file="lib/VMCore/Module.cpp"
|
||||
@ -802,17 +802,17 @@ CPP
|
||||
CXX
|
||||
CXXFLAGS
|
||||
CCC'
|
||||
ac_subdirs_all='projects/sample
|
||||
ac_subdirs_all='projects/llvm-gcc
|
||||
projects/test-suite
|
||||
projects/llvm-test
|
||||
projects/poolalloc
|
||||
projects/llvm-poolalloc
|
||||
projects/sample
|
||||
projects/privbracket
|
||||
projects/llvm-stacker
|
||||
projects/llvm-test
|
||||
projects/test-suite
|
||||
projects/llvm-reopt
|
||||
projects/llvm-gcc
|
||||
projects/llvm-java
|
||||
projects/llvm-tv
|
||||
projects/llvm-poolalloc
|
||||
projects/poolalloc
|
||||
projects/safecode
|
||||
projects/llvm-kernel'
|
||||
|
||||
@ -1316,7 +1316,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures llvm 2.7svn to adapt to many kinds of systems.
|
||||
\`configure' configures llvm 2.8svn to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1382,7 +1382,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of llvm 2.7svn:";;
|
||||
short | recursive ) echo "Configuration of llvm 2.8svn:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1533,7 +1533,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
llvm configure 2.7svn
|
||||
llvm configure 2.8svn
|
||||
generated by GNU Autoconf 2.60
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@ -1541,7 +1541,7 @@ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
This configure script is free software; the Free Software Foundation
|
||||
gives unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign.
|
||||
Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign.
|
||||
_ACEOF
|
||||
exit
|
||||
fi
|
||||
@ -1549,7 +1549,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by llvm $as_me 2.7svn, which was
|
||||
It was created by llvm $as_me 2.8svn, which was
|
||||
generated by GNU Autoconf 2.60. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -1903,7 +1903,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
|
||||
LLVM_COPYRIGHT="Copyright (c) 2003-2009 University of Illinois at Urbana-Champaign."
|
||||
LLVM_COPYRIGHT="Copyright (c) 2003-2010 University of Illinois at Urbana-Champaign."
|
||||
|
||||
|
||||
|
||||
@ -1951,6 +1951,33 @@ echo "$as_me: error: Already configured in ${srcdir}" >&2;}
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test -d ${srcdir}/projects/llvm-gcc ; then
|
||||
subdirs="$subdirs projects/llvm-gcc"
|
||||
|
||||
fi
|
||||
|
||||
if test -d ${srcdir}/projects/test-suite ; then
|
||||
subdirs="$subdirs projects/test-suite"
|
||||
|
||||
fi
|
||||
|
||||
if test -d ${srcdir}/projects/llvm-test ; then
|
||||
subdirs="$subdirs projects/llvm-test"
|
||||
|
||||
fi
|
||||
|
||||
if test -d ${srcdir}/projects/poolalloc ; then
|
||||
subdirs="$subdirs projects/poolalloc"
|
||||
|
||||
fi
|
||||
|
||||
if test -d ${srcdir}/projects/llvm-poolalloc ; then
|
||||
subdirs="$subdirs projects/llvm-poolalloc"
|
||||
|
||||
fi
|
||||
|
||||
for i in `ls ${srcdir}/projects`
|
||||
do
|
||||
if test -d ${srcdir}/projects/${i} ; then
|
||||
@ -1961,25 +1988,13 @@ do
|
||||
privbracket) subdirs="$subdirs projects/privbracket"
|
||||
;;
|
||||
llvm-stacker) subdirs="$subdirs projects/llvm-stacker"
|
||||
;;
|
||||
# llvm-test is the old name of the test-suite, kept here for backwards
|
||||
# compatibility
|
||||
llvm-test) subdirs="$subdirs projects/llvm-test"
|
||||
;;
|
||||
test-suite) subdirs="$subdirs projects/test-suite"
|
||||
;;
|
||||
llvm-reopt) subdirs="$subdirs projects/llvm-reopt"
|
||||
;;
|
||||
llvm-gcc) subdirs="$subdirs projects/llvm-gcc"
|
||||
;;
|
||||
llvm-java) subdirs="$subdirs projects/llvm-java"
|
||||
;;
|
||||
llvm-tv) subdirs="$subdirs projects/llvm-tv"
|
||||
;;
|
||||
llvm-poolalloc) subdirs="$subdirs projects/llvm-poolalloc"
|
||||
;;
|
||||
poolalloc) subdirs="$subdirs projects/poolalloc"
|
||||
;;
|
||||
safecode) subdirs="$subdirs projects/safecode"
|
||||
;;
|
||||
llvm-kernel) subdirs="$subdirs projects/llvm-kernel"
|
||||
@ -11136,7 +11151,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 11139 "configure"
|
||||
#line 11154 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -20608,7 +20623,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by llvm $as_me 2.7svn, which was
|
||||
This file was extended by llvm $as_me 2.8svn, which was
|
||||
generated by GNU Autoconf 2.60. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -20661,7 +20676,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
llvm config.status 2.7svn
|
||||
llvm config.status 2.8svn
|
||||
configured by $0, generated by GNU Autoconf 2.60,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
@ -10,6 +10,9 @@
|
||||
|
||||
<div class="doc_title">LLVM 2.7 Release Notes</div>
|
||||
|
||||
<img align=right src="http://llvm.org/img/DragonSmall.png"
|
||||
width="136" height="136">
|
||||
|
||||
<ol>
|
||||
<li><a href="#intro">Introduction</a></li>
|
||||
<li><a href="#subproj">Sub-project Status Update</a></li>
|
||||
@ -48,14 +51,18 @@ href="http://llvm.org/releases/">LLVM releases web site</a>.</p>
|
||||
<p>For more information about LLVM, including information about the latest
|
||||
release, please check out the <a href="http://llvm.org/">main LLVM
|
||||
web site</a>. If you have questions or comments, the <a
|
||||
href="http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVM Developer's Mailing
|
||||
List</a> is a good place to send them.</p>
|
||||
href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVM Developer's
|
||||
Mailing List</a> is a good place to send them.</p>
|
||||
|
||||
<p>Note that if you are reading this file from a Subversion checkout or the
|
||||
main LLVM web page, this document applies to the <i>next</i> release, not the
|
||||
current one. To see the release notes for a specific release, please see the
|
||||
<a href="http://llvm.org/releases/">releases page</a>.</p>
|
||||
|
||||
|
||||
<p>FIXME: llvm.org moved to new server, mention new logo, Ted and Doug new code
|
||||
owners.</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@ -66,6 +73,7 @@ Almost dead code.
|
||||
llvm/Analysis/PointerTracking.h => Edwin wants this, consider for 2.8.
|
||||
ABCD, SCCVN, GEPSplitterPass
|
||||
MSIL backend?
|
||||
lib/Transforms/Utils/SSI.cpp -> ABCD depends on it.
|
||||
-->
|
||||
|
||||
|
||||
@ -78,8 +86,6 @@ Almost dead code.
|
||||
loop dependence analysis
|
||||
ELF Writer? How stable?
|
||||
<li>PostRA scheduler improvements, ARM adoption (David Goodwin).</li>
|
||||
2.7 supports the GDB 7.0 jit interfaces for debug info.
|
||||
2.7 eliminates ADT/iterator.h
|
||||
-->
|
||||
|
||||
<!-- for announcement email:
|
||||
@ -88,8 +94,7 @@ Almost dead code.
|
||||
compiler_rt
|
||||
KLEE web page at klee.llvm.org
|
||||
Many new papers added to /pubs/
|
||||
Mention gcc plugin.
|
||||
|
||||
Mention gcc plugin.
|
||||
-->
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
@ -123,6 +128,7 @@ development. Here we include updates on these subprojects.
|
||||
|
||||
<ul>
|
||||
<li>...</li>
|
||||
include a link to cxx_compatibility.html
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -139,7 +145,7 @@ href="http://clang.llvm.org/StaticAnalysis.html">automatically finding bugs</a>
|
||||
in C and Objective-C programs. The tool performs checks to find
|
||||
bugs that occur on a specific path within a program.</p>
|
||||
|
||||
<p>In the LLVM 2.7 time-frame, the analyzer core has ...</p>
|
||||
<p>In the LLVM 2.7 time-frame, the analyzer core has sprouted legs and...</p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -190,24 +196,6 @@ License, a "BSD-style" license.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_subsection">
|
||||
<a name="klee">KLEE: Symbolic Execution and Automatic Test Case Generator</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
The new LLVM <a href="http://klee.llvm.org/">KLEE project</a> is a symbolic
|
||||
execution framework for programs in LLVM bitcode form. KLEE tries to
|
||||
symbolically evaluate "all" paths through the application and records state
|
||||
transitions that lead to fault states. This allows it to construct testcases
|
||||
that lead to faults and can even be used to verify algorithms. For more
|
||||
details, please see the <a
|
||||
href="http://llvm.org/pubs/2008-12-OSDI-KLEE.html">OSDI 2008 paper</a> about
|
||||
KLEE.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_subsection">
|
||||
<a name="dragonegg">DragonEgg: GCC-4.5 as an LLVM frontend</a>
|
||||
@ -257,6 +245,8 @@ The LLVM Machine Code (MC) Toolkit project is ...
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
Need update.
|
||||
<!--
|
||||
<p><a href="http://github.com/evanphx/rubinius">Rubinius</a> is an environment
|
||||
for running Ruby code which strives to write as much of the core class
|
||||
implementation in Ruby as possible. Combined with a bytecode interpreting VM, it
|
||||
@ -266,6 +256,7 @@ remove dynamism from ruby execution and increase performance.</p>
|
||||
|
||||
<p>Since LLVM 2.5, Rubinius has made several major leaps forward, implementing
|
||||
a counter based JIT, type feedback and speculative method inlining.
|
||||
-->
|
||||
</p>
|
||||
|
||||
</div>
|
||||
@ -278,6 +269,8 @@ a counter based JIT, type feedback and speculative method inlining.
|
||||
<div class="doc_text">
|
||||
|
||||
<p>
|
||||
Need update.
|
||||
<!--
|
||||
<a href="http://macruby.org">MacRuby</a> is an implementation of Ruby on top of
|
||||
core Mac OS X technologies, such as the Objective-C common runtime and garbage
|
||||
collector and the CoreFoundation framework. It is principally developed by
|
||||
@ -287,7 +280,7 @@ Apple and aims at enabling the creation of full-fledged Mac OS X applications.
|
||||
<p>
|
||||
MacRuby uses LLVM for optimization passes, JIT and AOT compilation of Ruby
|
||||
expressions. It also uses zero-cost DWARF exceptions to implement Ruby exception
|
||||
handling.</p>
|
||||
handling.--> </p>
|
||||
|
||||
</div>
|
||||
|
||||
@ -308,9 +301,9 @@ built-in list and matrix support (including list and matrix comprehensions) and
|
||||
an easy-to-use C interface. The interpreter uses LLVM as a backend to
|
||||
JIT-compile Pure programs to fast native code.</p>
|
||||
|
||||
<p>Pure versions ??? and later have been tested and are known to work with
|
||||
LLVM 2.7 (and continue to work with older LLVM releases >= 2.3 as well).
|
||||
</p>
|
||||
<p>Pure versions 0.43 and later have been tested and are known to work with
|
||||
LLVM 2.7 (and continue to work with older LLVM releases >= 2.5).</p>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@ -321,6 +314,8 @@ LLVM 2.7 (and continue to work with older LLVM releases >= 2.3 as well).
|
||||
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
Need update.
|
||||
<!--
|
||||
<a href="http://www.dsource.org/projects/ldc">LDC</a> is an implementation of
|
||||
the D Programming Language using the LLVM optimizer and code generator.
|
||||
The LDC project works great with the LLVM 2.6 release. General improvements in
|
||||
@ -328,7 +323,7 @@ this
|
||||
cycle have included new inline asm constraint handling, better debug info
|
||||
support, general bug fixes and better x86-64 support. This has allowed
|
||||
some major improvements in LDC, getting it much closer to being as
|
||||
fully featured as the original DMD compiler from DigitalMars.
|
||||
fully featured as the original DMD compiler from DigitalMars.-->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -342,7 +337,8 @@ fully featured as the original DMD compiler from DigitalMars.
|
||||
<a href="http://code.roadsend.com/rphp">Roadsend PHP</a> (rphp) is an open
|
||||
source implementation of the PHP programming
|
||||
language that uses LLVM for its optimizer, JIT and static compiler. This is a
|
||||
reimplementation of an earlier project that is now based on LLVM.</p>
|
||||
reimplementation of an earlier project that is now based on LLVM.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
@ -355,7 +351,8 @@ reimplementation of an earlier project that is now based on LLVM.</p>
|
||||
<a href="http://code.google.com/p/unladen-swallow/">Unladen Swallow</a> is a
|
||||
branch of <a href="http://python.org/">Python</a> intended to be fully
|
||||
compatible and significantly faster. It uses LLVM's optimization passes and JIT
|
||||
compiler.</p>
|
||||
compiler.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
@ -365,10 +362,13 @@ compiler.</p>
|
||||
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
Need update.
|
||||
<!--
|
||||
<a href="http://code.google.com/p/llvm-lua/">LLVM-Lua</a> uses LLVM to add JIT
|
||||
and static compiling support to the Lua VM. Lua bytecode is analyzed to
|
||||
remove type checks, then LLVM is used to compile the bytecode down to machine
|
||||
code.</p>
|
||||
code.-->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
@ -378,13 +378,15 @@ code.</p>
|
||||
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
Need update.
|
||||
<!--
|
||||
<a href="http://icedtea.classpath.org/wiki/Main_Page">IcedTea</a> provides a
|
||||
harness to build OpenJDK using only free software build tools and to provide
|
||||
replacements for the not-yet free parts of OpenJDK. One of the extensions that
|
||||
IcedTea provides is a new JIT compiler named <a
|
||||
href="http://icedtea.classpath.org/wiki/ZeroSharkFaq">Shark</a> which uses LLVM
|
||||
to provide native code generation without introducing processor-dependent
|
||||
code.
|
||||
code.-->
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -418,6 +420,54 @@ in this section.
|
||||
<li>...</li>
|
||||
</ul>
|
||||
|
||||
Extensible metadata solid.
|
||||
|
||||
Debug info improvements: using metadata instead of llvm.dbg global variables.
|
||||
This brings several enhancements including improved compile times.
|
||||
|
||||
New instruction selector.
|
||||
GHC Haskell ABI/ calling conv support.
|
||||
Pre-Alpha support for unions in IR.
|
||||
New InlineHint and StackAlignment function attributes
|
||||
Code generator MC'ized except for debug info and EH.
|
||||
New SCEV AA pass: -scev-aa
|
||||
Inliner reuses arrays allocas when inlining multiple callers to reduce stack usage.
|
||||
MC encoding and disassembler apis.
|
||||
Optimal Edge Profiling?
|
||||
Instcombine is now a library, has its own IRBuilder to simplify itself.
|
||||
New llvm/Support/Regex.h API. FileCheck now does regex's
|
||||
Many subtle pointer invalidation bugs in Callgraph have been fixed and it now uses asserting value handles.
|
||||
MC Disassembler (with blog post), MCInstPrinter. Many X86 backend and AsmPrinter simplifications
|
||||
Various tools like llc and opt now read either .ll or .bc files as input.
|
||||
Malloc and free instructions got removed.
|
||||
compiler-rt support for ARM.
|
||||
completely llvm-gcc NEON support.
|
||||
Can transcode from GAS to intel syntax with "llvm-mc foo.s -output-asm-variant=1"
|
||||
JIT debug information with GDB 7.0
|
||||
New CodeGen Level CSE
|
||||
CMake can now run tests, what other improvements?
|
||||
ARM/Thumb using reg scavenging for stack object address materialization (PEI).
|
||||
New SSAUpdater and MachineSSAUpdater classes for unstructured ssa updating,
|
||||
changed jump threading, GVN, etc to use it which simplified them and speed
|
||||
them up.
|
||||
Combiner-AA improvements, why not on by default?
|
||||
Pre-regalloc tail duplication
|
||||
x86 sibcall optimization
|
||||
New LSR with full strength reduction mode
|
||||
The most awesome sext / zext optimization pass. ?
|
||||
|
||||
|
||||
|
||||
CondProp pass removed (functionality merged into jump threading).
|
||||
AndersAA got removed (from 2.7 or mainline?)
|
||||
PredSimplify, LoopVR, GVNPRE got removed.
|
||||
LLVM command line tools now overwrite their output, before they would only do this with -f.
|
||||
DOUT removed, use DEBUG(errs() instead.
|
||||
Much stuff converted to use raw_ostream instead of std::ostream.
|
||||
TargetAsmInfo renamed to MCAsmInfo
|
||||
llvm/ADT/iterator.h gone.
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
@ -699,13 +749,7 @@ listed by component. If you run into a problem, please check the <a
|
||||
href="http://llvm.org/bugs/">LLVM bug database</a> and submit a bug if
|
||||
there isn't already one.</p>
|
||||
|
||||
<ul>
|
||||
<li>The llvm-gcc bootstrap will fail with some versions of binutils (e.g. 2.15)
|
||||
with a message of "<tt><a href="http://llvm.org/PR5004">Error: can not do 8
|
||||
byte pc-relative relocation</a></tt>" when building C++ code. We intend to
|
||||
fix this on mainline, but a workaround is to upgrade to binutils 2.17 or
|
||||
later.</li>
|
||||
|
||||
<ul>
|
||||
<li>LLVM will not correctly compile on Solaris and/or OpenSolaris
|
||||
using the stock GCC 3.x.x series 'out the box',
|
||||
See: <a href="GettingStarted.html#brokengcc">Broken versions of GCC and other tools</a>.
|
||||
@ -731,10 +775,11 @@ components, please contact us on the <a
|
||||
href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVMdev list</a>.</p>
|
||||
|
||||
<ul>
|
||||
<li>The MSIL, Alpha, SPU, MIPS, PIC16, Blackfin, MSP430 and SystemZ backends are
|
||||
experimental.</li>
|
||||
<li>The MSIL, Alpha, SPU, MIPS, PIC16, Blackfin, MSP430, SystemZ and MicroBlaze
|
||||
backends are experimental.</li>
|
||||
<li>The <tt>llc</tt> "<tt>-filetype=asm</tt>" (the default) is the only
|
||||
supported value for this option. The ELF writer is experimental.</li>
|
||||
supported value for this option. The MachO writer is experimental, and
|
||||
works much better in mainline SVN.</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@ -865,7 +910,7 @@ appropriate nops inserted to ensure restartability.</li>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="c-fe">Known problems with the llvm-gcc C front-end</a>
|
||||
<a name="c-fe">Known problems with the llvm-gcc C and C++ front-end</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
@ -881,24 +926,6 @@ appropriate nops inserted to ensure restartability.</li>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="c++-fe">Known problems with the llvm-gcc C++ front-end</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The C++ front-end is considered to be fully
|
||||
tested and works for a number of non-trivial programs, including LLVM
|
||||
itself, Qt, Mozilla, etc.</p>
|
||||
|
||||
<ul>
|
||||
<li>Exception handling works well on the X86 and PowerPC targets. Currently
|
||||
only Linux and Darwin targets are supported (both 32 and 64 bit).</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="fortran-fe">Known problems with the llvm-gcc Fortran front-end</a>
|
||||
@ -997,7 +1024,7 @@ lists</a>.</p>
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
|
||||
<a href="http://llvm.org/">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-03-01 20:29:17 +0100 (Mon, 01 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-19 04:18:05 +0100 (Fri, 19 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -237,7 +237,7 @@ height="369">
|
||||
<p>LLVM debugging information has been carefully designed to make it possible
|
||||
for the optimizer to optimize the program and debugging information without
|
||||
necessarily having to know anything about debugging information. In
|
||||
particular, te use of metadadta avoids duplicated dubgging information from
|
||||
particular, the use of metadata avoids duplicated debugging information from
|
||||
the beginning, and the global dead code elimination pass automatically
|
||||
deletes debugging information for a function if it decides to delete the
|
||||
function. </p>
|
||||
@ -370,7 +370,7 @@ height="369">
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>These descriptors contain informations for a file. Global variables and top
|
||||
<p>These descriptors contain information for a file. Global variables and top
|
||||
level functions would be defined using this context.k File descriptors also
|
||||
provide context for source line correspondence. </p>
|
||||
|
||||
@ -967,7 +967,7 @@ call void @llvm.dbg.declare({ }* %2, metadata !12), !dbg !14
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>Here <tt>!14</tt> indicates that <tt>Z</tt> is declaread at line number 5 and
|
||||
<p>Here <tt>!14</tt> indicates that <tt>Z</tt> is declared at line number 5 and
|
||||
column number 9 inside of lexical scope <tt>!13</tt>. The lexical scope
|
||||
itself resides inside of lexical scope <tt>!1</tt> described above.</p>
|
||||
|
||||
@ -1762,7 +1762,7 @@ enum Trees {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-03-09 01:44:10 +0100 (Tue, 09 Mar 2010) $
|
||||
Last modified: $Date: 2010-03-17 16:01:50 +0100 (Wed, 17 Mar 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -329,7 +329,8 @@ class BitVector {
|
||||
Size = RHS.size();
|
||||
unsigned RHSWords = NumBitWords(Size);
|
||||
if (Size <= Capacity * BITWORD_SIZE) {
|
||||
std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits);
|
||||
if (Size)
|
||||
std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits);
|
||||
clear_unused_bits();
|
||||
return *this;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define LLVM_ADT_EQUIVALENCECLASSES_H
|
||||
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <cassert>
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
|
@ -23,6 +23,7 @@
|
||||
namespace llvm {
|
||||
class APFloat;
|
||||
class APInt;
|
||||
class BumpPtrAllocator;
|
||||
|
||||
/// This folding set used for two purposes:
|
||||
/// 1. Given information about a node we want to create, look up the unique
|
||||
@ -197,6 +198,23 @@ template<typename T> struct FoldingSetTrait {
|
||||
static inline void Profile(T& X, FoldingSetNodeID& ID) { X.Profile(ID); }
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// FoldingSetNodeIDRef - This class describes a reference to an interned
|
||||
/// FoldingSetNodeID, which can be a useful to store node id data rather
|
||||
/// than using plain FoldingSetNodeIDs, since the 32-element SmallVector
|
||||
/// is often much larger than necessary, and the possibility of heap
|
||||
/// allocation means it requires a non-trivial destructor call.
|
||||
class FoldingSetNodeIDRef {
|
||||
unsigned* Data;
|
||||
size_t Size;
|
||||
public:
|
||||
FoldingSetNodeIDRef() : Data(0), Size(0) {}
|
||||
FoldingSetNodeIDRef(unsigned *D, size_t S) : Data(D), Size(S) {}
|
||||
|
||||
unsigned *getData() const { return Data; }
|
||||
size_t getSize() const { return Size; }
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// FoldingSetNodeID - This class is used to gather all the unique data bits of
|
||||
/// a node. When all the bits are gathered this class is used to produce a
|
||||
@ -210,11 +228,8 @@ class FoldingSetNodeID {
|
||||
public:
|
||||
FoldingSetNodeID() {}
|
||||
|
||||
/// getRawData - Return the ith entry in the Bits data.
|
||||
///
|
||||
unsigned getRawData(unsigned i) const {
|
||||
return Bits[i];
|
||||
}
|
||||
FoldingSetNodeID(FoldingSetNodeIDRef Ref)
|
||||
: Bits(Ref.getData(), Ref.getData() + Ref.getSize()) {}
|
||||
|
||||
/// Add* - Add various data types to Bit data.
|
||||
///
|
||||
@ -242,6 +257,11 @@ class FoldingSetNodeID {
|
||||
/// operator== - Used to compare two nodes to each other.
|
||||
///
|
||||
bool operator==(const FoldingSetNodeID &RHS) const;
|
||||
|
||||
/// Intern - Copy this node's data to a memory region allocated from the
|
||||
/// given allocator and return a FoldingSetNodeIDRef describing the
|
||||
/// interned data.
|
||||
FoldingSetNodeIDRef Intern(BumpPtrAllocator &Allocator) const;
|
||||
};
|
||||
|
||||
// Convenience type to hide the implementation of the folding set.
|
||||
|
@ -57,17 +57,18 @@ class SmallVectorBase {
|
||||
// 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.
|
||||
struct U {
|
||||
#ifdef __GNUC__
|
||||
typedef char U;
|
||||
U FirstEl __attribute__((aligned));
|
||||
char X __attribute__((aligned));
|
||||
#else
|
||||
union U {
|
||||
double D;
|
||||
long double LD;
|
||||
long long L;
|
||||
void *P;
|
||||
} FirstEl;
|
||||
union {
|
||||
double D;
|
||||
long double LD;
|
||||
long long L;
|
||||
void *P;
|
||||
} X;
|
||||
#endif
|
||||
} FirstEl;
|
||||
// Space after 'FirstEl' is clobbered, do not add any instance vars after it.
|
||||
|
||||
protected:
|
||||
|
@ -49,7 +49,11 @@ namespace llvm {
|
||||
/// are opaque objects that the client is not allowed to do much with
|
||||
/// directly.
|
||||
///
|
||||
class SCEV : public FastFoldingSetNode {
|
||||
class SCEV : public FoldingSetNode {
|
||||
/// FastID - A reference to an Interned FoldingSetNodeID for this node.
|
||||
/// The ScalarEvolution's BumpPtrAllocator holds the data.
|
||||
FoldingSetNodeIDRef FastID;
|
||||
|
||||
// The SCEV baseclass this node corresponds to
|
||||
const unsigned short SCEVType;
|
||||
|
||||
@ -64,11 +68,14 @@ namespace llvm {
|
||||
protected:
|
||||
virtual ~SCEV();
|
||||
public:
|
||||
explicit SCEV(const FoldingSetNodeID &ID, unsigned SCEVTy) :
|
||||
FastFoldingSetNode(ID), SCEVType(SCEVTy), SubclassData(0) {}
|
||||
explicit SCEV(const FoldingSetNodeIDRef ID, unsigned SCEVTy) :
|
||||
FastID(ID), SCEVType(SCEVTy), SubclassData(0) {}
|
||||
|
||||
unsigned getSCEVType() const { return SCEVType; }
|
||||
|
||||
/// Profile - FoldingSet support.
|
||||
void Profile(FoldingSetNodeID& ID) { ID = FastID; }
|
||||
|
||||
/// isLoopInvariant - Return true if the value of this SCEV is unchanging in
|
||||
/// the specified loop.
|
||||
virtual bool isLoopInvariant(const Loop *L) const = 0;
|
||||
|
@ -79,12 +79,7 @@ namespace llvm {
|
||||
/// expandCodeFor - Insert code to directly compute the specified SCEV
|
||||
/// expression into the program. The inserted code is inserted into the
|
||||
/// specified block.
|
||||
Value *expandCodeFor(const SCEV *SH, const Type *Ty, Instruction *I) {
|
||||
BasicBlock::iterator IP = I;
|
||||
while (isInsertedInstruction(IP)) ++IP;
|
||||
Builder.SetInsertPoint(IP->getParent(), IP);
|
||||
return expandCodeFor(SH, Ty);
|
||||
}
|
||||
Value *expandCodeFor(const SCEV *SH, const Type *Ty, Instruction *I);
|
||||
|
||||
/// setIVIncInsertPos - Set the current IV increment loop and position.
|
||||
void setIVIncInsertPos(const Loop *L, Instruction *Pos) {
|
||||
@ -109,6 +104,13 @@ namespace llvm {
|
||||
/// is useful for late optimization passes.
|
||||
void disableCanonicalMode() { CanonicalMode = false; }
|
||||
|
||||
/// clearInsertPoint - Clear the current insertion point. This is useful
|
||||
/// if the instruction that had been serving as the insertion point may
|
||||
/// have been deleted.
|
||||
void clearInsertPoint() {
|
||||
Builder.ClearInsertionPoint();
|
||||
}
|
||||
|
||||
private:
|
||||
LLVMContext &getContext() const { return SE.getContext(); }
|
||||
|
||||
|
@ -37,7 +37,7 @@ namespace llvm {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
ConstantInt *V;
|
||||
SCEVConstant(const FoldingSetNodeID &ID, ConstantInt *v) :
|
||||
SCEVConstant(const FoldingSetNodeIDRef ID, ConstantInt *v) :
|
||||
SCEV(ID, scConstant), V(v) {}
|
||||
public:
|
||||
ConstantInt *getValue() const { return V; }
|
||||
@ -81,7 +81,7 @@ namespace llvm {
|
||||
const SCEV *Op;
|
||||
const Type *Ty;
|
||||
|
||||
SCEVCastExpr(const FoldingSetNodeID &ID,
|
||||
SCEVCastExpr(const FoldingSetNodeIDRef ID,
|
||||
unsigned SCEVTy, const SCEV *op, const Type *ty);
|
||||
|
||||
public:
|
||||
@ -120,7 +120,7 @@ namespace llvm {
|
||||
class SCEVTruncateExpr : public SCEVCastExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVTruncateExpr(const FoldingSetNodeID &ID,
|
||||
SCEVTruncateExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, const Type *ty);
|
||||
|
||||
public:
|
||||
@ -140,7 +140,7 @@ namespace llvm {
|
||||
class SCEVZeroExtendExpr : public SCEVCastExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVZeroExtendExpr(const FoldingSetNodeID &ID,
|
||||
SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, const Type *ty);
|
||||
|
||||
public:
|
||||
@ -160,7 +160,7 @@ namespace llvm {
|
||||
class SCEVSignExtendExpr : public SCEVCastExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVSignExtendExpr(const FoldingSetNodeID &ID,
|
||||
SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, const Type *ty);
|
||||
|
||||
public:
|
||||
@ -180,25 +180,27 @@ namespace llvm {
|
||||
///
|
||||
class SCEVNAryExpr : public SCEV {
|
||||
protected:
|
||||
SmallVector<const SCEV *, 8> Operands;
|
||||
// Since SCEVs are immutable, ScalarEvolution allocates operand
|
||||
// arrays with its SCEVAllocator, so this class just needs a simple
|
||||
// pointer rather than a more elaborate vector-like data structure.
|
||||
// This also avoids the need for a non-trivial destructor.
|
||||
const SCEV *const *Operands;
|
||||
size_t NumOperands;
|
||||
|
||||
SCEVNAryExpr(const FoldingSetNodeID &ID,
|
||||
enum SCEVTypes T, const SmallVectorImpl<const SCEV *> &ops)
|
||||
: SCEV(ID, T), Operands(ops.begin(), ops.end()) {}
|
||||
SCEVNAryExpr(const FoldingSetNodeIDRef ID,
|
||||
enum SCEVTypes T, const SCEV *const *O, size_t N)
|
||||
: SCEV(ID, T), Operands(O), NumOperands(N) {}
|
||||
|
||||
public:
|
||||
unsigned getNumOperands() const { return (unsigned)Operands.size(); }
|
||||
size_t getNumOperands() const { return NumOperands; }
|
||||
const SCEV *getOperand(unsigned i) const {
|
||||
assert(i < Operands.size() && "Operand index out of range!");
|
||||
assert(i < NumOperands && "Operand index out of range!");
|
||||
return Operands[i];
|
||||
}
|
||||
|
||||
const SmallVectorImpl<const SCEV *> &getOperands() const {
|
||||
return Operands;
|
||||
}
|
||||
typedef SmallVectorImpl<const SCEV *>::const_iterator op_iterator;
|
||||
op_iterator op_begin() const { return Operands.begin(); }
|
||||
op_iterator op_end() const { return Operands.end(); }
|
||||
typedef const SCEV *const *op_iterator;
|
||||
op_iterator op_begin() const { return Operands; }
|
||||
op_iterator op_end() const { return Operands + NumOperands; }
|
||||
|
||||
virtual bool isLoopInvariant(const Loop *L) const {
|
||||
for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
|
||||
@ -260,10 +262,9 @@ namespace llvm {
|
||||
///
|
||||
class SCEVCommutativeExpr : public SCEVNAryExpr {
|
||||
protected:
|
||||
SCEVCommutativeExpr(const FoldingSetNodeID &ID,
|
||||
enum SCEVTypes T,
|
||||
const SmallVectorImpl<const SCEV *> &ops)
|
||||
: SCEVNAryExpr(ID, T, ops) {}
|
||||
SCEVCommutativeExpr(const FoldingSetNodeIDRef ID,
|
||||
enum SCEVTypes T, const SCEV *const *O, size_t N)
|
||||
: SCEVNAryExpr(ID, T, O, N) {}
|
||||
|
||||
public:
|
||||
virtual const char *getOperationStr() const = 0;
|
||||
@ -287,9 +288,9 @@ namespace llvm {
|
||||
class SCEVAddExpr : public SCEVCommutativeExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVAddExpr(const FoldingSetNodeID &ID,
|
||||
const SmallVectorImpl<const SCEV *> &ops)
|
||||
: SCEVCommutativeExpr(ID, scAddExpr, ops) {
|
||||
SCEVAddExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N)
|
||||
: SCEVCommutativeExpr(ID, scAddExpr, O, N) {
|
||||
}
|
||||
|
||||
public:
|
||||
@ -315,9 +316,9 @@ namespace llvm {
|
||||
class SCEVMulExpr : public SCEVCommutativeExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVMulExpr(const FoldingSetNodeID &ID,
|
||||
const SmallVectorImpl<const SCEV *> &ops)
|
||||
: SCEVCommutativeExpr(ID, scMulExpr, ops) {
|
||||
SCEVMulExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N)
|
||||
: SCEVCommutativeExpr(ID, scMulExpr, O, N) {
|
||||
}
|
||||
|
||||
public:
|
||||
@ -339,7 +340,7 @@ namespace llvm {
|
||||
|
||||
const SCEV *LHS;
|
||||
const SCEV *RHS;
|
||||
SCEVUDivExpr(const FoldingSetNodeID &ID, const SCEV *lhs, const SCEV *rhs)
|
||||
SCEVUDivExpr(const FoldingSetNodeIDRef ID, const SCEV *lhs, const SCEV *rhs)
|
||||
: SCEV(ID, scUDivExpr), LHS(lhs), RHS(rhs) {}
|
||||
|
||||
public:
|
||||
@ -389,10 +390,10 @@ namespace llvm {
|
||||
|
||||
const Loop *L;
|
||||
|
||||
SCEVAddRecExpr(const FoldingSetNodeID &ID,
|
||||
const SmallVectorImpl<const SCEV *> &ops, const Loop *l)
|
||||
: SCEVNAryExpr(ID, scAddRecExpr, ops), L(l) {
|
||||
for (size_t i = 0, e = Operands.size(); i != e; ++i)
|
||||
SCEVAddRecExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N, const Loop *l)
|
||||
: SCEVNAryExpr(ID, scAddRecExpr, O, N), L(l) {
|
||||
for (size_t i = 0, e = NumOperands; i != e; ++i)
|
||||
assert(Operands[i]->isLoopInvariant(l) &&
|
||||
"Operands of AddRec must be loop-invariant!");
|
||||
}
|
||||
@ -471,9 +472,9 @@ namespace llvm {
|
||||
class SCEVSMaxExpr : public SCEVCommutativeExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVSMaxExpr(const FoldingSetNodeID &ID,
|
||||
const SmallVectorImpl<const SCEV *> &ops)
|
||||
: SCEVCommutativeExpr(ID, scSMaxExpr, ops) {
|
||||
SCEVSMaxExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N)
|
||||
: SCEVCommutativeExpr(ID, scSMaxExpr, O, N) {
|
||||
// Max never overflows.
|
||||
setHasNoUnsignedWrap(true);
|
||||
setHasNoSignedWrap(true);
|
||||
@ -496,9 +497,9 @@ namespace llvm {
|
||||
class SCEVUMaxExpr : public SCEVCommutativeExpr {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
SCEVUMaxExpr(const FoldingSetNodeID &ID,
|
||||
const SmallVectorImpl<const SCEV *> &ops)
|
||||
: SCEVCommutativeExpr(ID, scUMaxExpr, ops) {
|
||||
SCEVUMaxExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *const *O, size_t N)
|
||||
: SCEVCommutativeExpr(ID, scUMaxExpr, O, N) {
|
||||
// Max never overflows.
|
||||
setHasNoUnsignedWrap(true);
|
||||
setHasNoSignedWrap(true);
|
||||
@ -523,7 +524,7 @@ namespace llvm {
|
||||
friend class ScalarEvolution;
|
||||
|
||||
Value *V;
|
||||
SCEVUnknown(const FoldingSetNodeID &ID, Value *v) :
|
||||
SCEVUnknown(const FoldingSetNodeIDRef ID, Value *v) :
|
||||
SCEV(ID, scUnknown), V(v) {}
|
||||
|
||||
public:
|
||||
|
@ -83,9 +83,9 @@ class MachineJumpTableInfo {
|
||||
/// getEntryAlignment - Return the alignment of each entry in the jump table.
|
||||
unsigned getEntryAlignment(const TargetData &TD) const;
|
||||
|
||||
/// getJumpTableIndex - Create a new jump table or return an existing one.
|
||||
/// createJumpTableIndex - Create a new jump table.
|
||||
///
|
||||
unsigned getJumpTableIndex(const std::vector<MachineBasicBlock*> &DestBBs);
|
||||
unsigned createJumpTableIndex(const std::vector<MachineBasicBlock*> &DestBBs);
|
||||
|
||||
/// isEmpty - Return true if there are no jump tables.
|
||||
///
|
||||
|
@ -2516,6 +2516,11 @@ class InvokeInst : public TerminatorInst {
|
||||
const Value *getCalledValue() const { return getOperand(0); }
|
||||
Value *getCalledValue() { return getOperand(0); }
|
||||
|
||||
/// setCalledFunction - Set the function called.
|
||||
void setCalledFunction(Value* Fn) {
|
||||
Op<0>() = Fn;
|
||||
}
|
||||
|
||||
// get*Dest - Return the destination basic blocks...
|
||||
BasicBlock *getNormalDest() const {
|
||||
return cast<BasicBlock>(getOperand(1));
|
||||
|
@ -892,7 +892,10 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.".
|
||||
def int_x86_sse42_crc32_32 : GCCBuiltin<"__builtin_ia32_crc32si">,
|
||||
Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_sse42_crc32_64 : GCCBuiltin<"__builtin_ia32_crc32di">,
|
||||
def int_x86_sse42_crc64_8 :
|
||||
Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i8_ty],
|
||||
[IntrNoMem]>;
|
||||
def int_x86_sse42_crc64_64 : GCCBuiltin<"__builtin_ia32_crc32di">,
|
||||
Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty],
|
||||
[IntrNoMem]>;
|
||||
}
|
||||
|
@ -24,8 +24,10 @@ class raw_ostream;
|
||||
class MCAsmLayout;
|
||||
class MCAssembler;
|
||||
class MCContext;
|
||||
class MCCodeEmitter;
|
||||
class MCExpr;
|
||||
class MCFragment;
|
||||
class MCObjectWriter;
|
||||
class MCSection;
|
||||
class MCSectionData;
|
||||
class MCSymbol;
|
||||
@ -35,7 +37,8 @@ class TargetAsmBackend;
|
||||
/// MCAsmFixup - Represent a fixed size region of bytes inside some fragment
|
||||
/// which needs to be rewritten. This region will either be rewritten by the
|
||||
/// assembler or cause a relocation entry to be generated.
|
||||
struct MCAsmFixup {
|
||||
class MCAsmFixup {
|
||||
public:
|
||||
/// Offset - The offset inside the fragment which needs to be rewritten.
|
||||
uint64_t Offset;
|
||||
|
||||
@ -45,14 +48,9 @@ struct MCAsmFixup {
|
||||
/// Kind - The fixup kind.
|
||||
MCFixupKind Kind;
|
||||
|
||||
/// FixedValue - The value to replace the fix up by.
|
||||
//
|
||||
// FIXME: This should not be here.
|
||||
uint64_t FixedValue;
|
||||
|
||||
public:
|
||||
MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, MCFixupKind _Kind)
|
||||
: Offset(_Offset), Value(&_Value), Kind(_Kind), FixedValue(0) {}
|
||||
: Offset(_Offset), Value(&_Value), Kind(_Kind) {}
|
||||
};
|
||||
|
||||
class MCFragment : public ilist_node<MCFragment> {
|
||||
@ -590,6 +588,8 @@ class MCAssembler {
|
||||
typedef SymbolDataListType::const_iterator const_symbol_iterator;
|
||||
typedef SymbolDataListType::iterator symbol_iterator;
|
||||
|
||||
typedef std::vector<IndirectSymbolData>::const_iterator
|
||||
const_indirect_symbol_iterator;
|
||||
typedef std::vector<IndirectSymbolData>::iterator indirect_symbol_iterator;
|
||||
|
||||
private:
|
||||
@ -600,6 +600,8 @@ class MCAssembler {
|
||||
|
||||
TargetAsmBackend &Backend;
|
||||
|
||||
MCCodeEmitter &Emitter;
|
||||
|
||||
raw_ostream &OS;
|
||||
|
||||
iplist<MCSectionData> Sections;
|
||||
@ -621,21 +623,6 @@ class MCAssembler {
|
||||
unsigned SubsectionsViaSymbols : 1;
|
||||
|
||||
private:
|
||||
/// Check whether a fixup can be satisfied, or whether it needs to be relaxed
|
||||
/// (increased in size, in order to hold its value correctly).
|
||||
bool FixupNeedsRelaxation(MCAsmFixup &Fixup, MCDataFragment *DF);
|
||||
|
||||
/// LayoutSection - Assign offsets and sizes to the fragments in the section
|
||||
/// \arg SD, and update the section size. The section file offset should
|
||||
/// already have been computed.
|
||||
void LayoutSection(MCSectionData &SD);
|
||||
|
||||
/// LayoutOnce - Perform one layout iteration and return true if any offsets
|
||||
/// were adjusted.
|
||||
bool LayoutOnce();
|
||||
|
||||
// FIXME: Make protected once we factor out object writer classes.
|
||||
public:
|
||||
/// Evaluate a fixup to a relocatable expression and the value which should be
|
||||
/// placed into the fixup.
|
||||
///
|
||||
@ -653,6 +640,44 @@ class MCAssembler {
|
||||
MCAsmFixup &Fixup, MCDataFragment *DF,
|
||||
MCValue &Target, uint64_t &Value) const;
|
||||
|
||||
/// Check whether a fixup can be satisfied, or whether it needs to be relaxed
|
||||
/// (increased in size, in order to hold its value correctly).
|
||||
bool FixupNeedsRelaxation(MCAsmFixup &Fixup, MCDataFragment *DF);
|
||||
|
||||
/// LayoutSection - Assign offsets and sizes to the fragments in the section
|
||||
/// \arg SD, and update the section size. The section file offset should
|
||||
/// already have been computed.
|
||||
void LayoutSection(MCSectionData &SD);
|
||||
|
||||
/// LayoutOnce - Perform one layout iteration and return true if any offsets
|
||||
/// were adjusted.
|
||||
bool LayoutOnce();
|
||||
|
||||
public:
|
||||
/// Find the symbol which defines the atom containing given address, inside
|
||||
/// the given section, or null if there is no such symbol.
|
||||
//
|
||||
// FIXME: Eliminate this, it is very slow.
|
||||
const MCSymbolData *getAtomForAddress(const MCSectionData *Section,
|
||||
uint64_t Address) const;
|
||||
|
||||
/// Find the symbol which defines the atom containing the given symbol, or
|
||||
/// null if there is no such symbol.
|
||||
//
|
||||
// FIXME: Eliminate this, it is very slow.
|
||||
const MCSymbolData *getAtom(const MCSymbolData *Symbol) const;
|
||||
|
||||
/// Check whether a particular symbol is visible to the linker and is required
|
||||
/// in the symbol table, or whether it can be discarded by the assembler. This
|
||||
/// also effects whether the assembler treats the label as potentially
|
||||
/// defining a separate atom.
|
||||
bool isSymbolLinkerVisible(const MCSymbolData *SD) const;
|
||||
|
||||
/// Emit the section contents using the given object writer.
|
||||
//
|
||||
// FIXME: Should MCAssembler always have a reference to the object writer?
|
||||
void WriteSectionData(const MCSectionData *Section, MCObjectWriter *OW) const;
|
||||
|
||||
public:
|
||||
/// Construct a new assembler instance.
|
||||
///
|
||||
@ -662,13 +687,16 @@ class MCAssembler {
|
||||
// concrete and require clients to pass in a target like object. The other
|
||||
// option is to make this abstract, and have targets provide concrete
|
||||
// implementations as we do with AsmParser.
|
||||
MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend, raw_ostream &OS);
|
||||
MCAssembler(MCContext &_Context, TargetAsmBackend &_Backend,
|
||||
MCCodeEmitter &_Emitter, raw_ostream &OS);
|
||||
~MCAssembler();
|
||||
|
||||
MCContext &getContext() const { return Context; }
|
||||
|
||||
TargetAsmBackend &getBackend() const { return Backend; }
|
||||
|
||||
MCCodeEmitter &getEmitter() const { return Emitter; }
|
||||
|
||||
/// Finish - Do final processing and write the object to the output stream.
|
||||
void Finish();
|
||||
|
||||
@ -723,10 +751,16 @@ class MCAssembler {
|
||||
indirect_symbol_iterator indirect_symbol_begin() {
|
||||
return IndirectSymbols.begin();
|
||||
}
|
||||
const_indirect_symbol_iterator indirect_symbol_begin() const {
|
||||
return IndirectSymbols.begin();
|
||||
}
|
||||
|
||||
indirect_symbol_iterator indirect_symbol_end() {
|
||||
return IndirectSymbols.end();
|
||||
}
|
||||
const_indirect_symbol_iterator indirect_symbol_end() const {
|
||||
return IndirectSymbols.end();
|
||||
}
|
||||
|
||||
size_t indirect_symbol_size() const { return IndirectSymbols.size(); }
|
||||
|
||||
|
@ -22,6 +22,12 @@ template<typename T> class SmallVectorImpl;
|
||||
|
||||
/// MCFixupKindInfo - Target independent information on a fixup kind.
|
||||
struct MCFixupKindInfo {
|
||||
enum FixupKindFlags {
|
||||
/// Is this fixup kind PCrelative. This is used by the assembler backend to
|
||||
/// evaluate fixup values in a target independent manner when possible.
|
||||
FKF_IsPCRel = (1 << 0)
|
||||
};
|
||||
|
||||
/// A target specific name for the fixup kind. The names will be unique for
|
||||
/// distinct kinds on any given target.
|
||||
const char *Name;
|
||||
@ -36,6 +42,9 @@ struct MCFixupKindInfo {
|
||||
/// The number of bits written by this fixup. The bits are assumed to be
|
||||
/// contiguous.
|
||||
unsigned TargetSize;
|
||||
|
||||
/// Flags describing additional information on this fixup kind.
|
||||
unsigned Flags;
|
||||
};
|
||||
|
||||
/// MCCodeEmitter - Generic instruction encoding interface.
|
||||
|
@ -73,9 +73,10 @@ namespace llvm {
|
||||
/// one if it does.
|
||||
///
|
||||
/// @param Name - The symbol name, for debugging purposes only, temporary
|
||||
/// symbols do not surive assembly. If non-empty the name must be unique
|
||||
/// across all symbols.
|
||||
MCSymbol *GetOrCreateTemporarySymbol(StringRef Name = "");
|
||||
/// symbols do not surive assembly.
|
||||
MCSymbol *GetOrCreateTemporarySymbol(StringRef Name) {
|
||||
return GetOrCreateSymbol(Name, true);
|
||||
}
|
||||
MCSymbol *GetOrCreateTemporarySymbol(const Twine &Name);
|
||||
|
||||
/// LookupSymbol - Get the symbol for \p Name, or null.
|
||||
|
162
include/llvm/MC/MCObjectWriter.h
Normal file
162
include/llvm/MC/MCObjectWriter.h
Normal file
@ -0,0 +1,162 @@
|
||||
//===-- llvm/MC/MCObjectWriter.h - Object File Writer Interface -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MCOBJECTWRITER_H
|
||||
#define LLVM_MC_MCOBJECTWRITER_H
|
||||
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmFixup;
|
||||
class MCAssembler;
|
||||
class MCDataFragment;
|
||||
class MCValue;
|
||||
class raw_ostream;
|
||||
|
||||
/// MCObjectWriter - Defines the object file and target independent interfaces
|
||||
/// used by the assembler backend to write native file format object files.
|
||||
///
|
||||
/// The object writer contains a few callbacks used by the assembler to allow
|
||||
/// the object writer to modify the assembler data structures at appropriate
|
||||
/// points. Once assembly is complete, the object writer is given the
|
||||
/// MCAssembler instance, which contains all the symbol and section data which
|
||||
/// should be emitted as part of WriteObject().
|
||||
///
|
||||
/// The object writer also contains a number of helper methods for writing
|
||||
/// binary data to the output stream.
|
||||
class MCObjectWriter {
|
||||
MCObjectWriter(const MCObjectWriter &); // DO NOT IMPLEMENT
|
||||
void operator=(const MCObjectWriter &); // DO NOT IMPLEMENT
|
||||
|
||||
protected:
|
||||
raw_ostream &OS;
|
||||
|
||||
unsigned IsLittleEndian : 1;
|
||||
|
||||
protected: // Can only create subclasses.
|
||||
MCObjectWriter(raw_ostream &_OS, bool _IsLittleEndian)
|
||||
: OS(_OS), IsLittleEndian(_IsLittleEndian) {}
|
||||
|
||||
public:
|
||||
virtual ~MCObjectWriter();
|
||||
|
||||
bool isLittleEndian() { return IsLittleEndian; }
|
||||
|
||||
raw_ostream &getStream() { return OS; }
|
||||
|
||||
/// @name High-Level API
|
||||
/// @{
|
||||
|
||||
/// Perform any late binding of symbols (for example, to assign symbol indices
|
||||
/// for use when generating relocations).
|
||||
///
|
||||
/// This routine is called by the assembler after layout and relaxation is
|
||||
/// complete.
|
||||
virtual void ExecutePostLayoutBinding(MCAssembler &Asm) = 0;
|
||||
|
||||
/// Record a relocation entry.
|
||||
///
|
||||
/// This routine is called by the assembler after layout and relaxation, and
|
||||
/// post layout binding. The implementation is responsible for storing
|
||||
/// information about the relocation so that it can be emitted during
|
||||
/// WriteObject().
|
||||
virtual void RecordRelocation(const MCAssembler &Asm,
|
||||
const MCDataFragment &Fragment,
|
||||
const MCAsmFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue) = 0;
|
||||
|
||||
/// Write the object file.
|
||||
///
|
||||
/// This routine is called by the assembler after layout and relaxation is
|
||||
/// complete, fixups have been evaluate and applied, and relocations
|
||||
/// generated.
|
||||
virtual void WriteObject(const MCAssembler &Asm) = 0;
|
||||
|
||||
/// @}
|
||||
/// @name Binary Output
|
||||
/// @{
|
||||
|
||||
void Write8(uint8_t Value) {
|
||||
OS << char(Value);
|
||||
}
|
||||
|
||||
void WriteLE16(uint16_t Value) {
|
||||
Write8(uint8_t(Value >> 0));
|
||||
Write8(uint8_t(Value >> 8));
|
||||
}
|
||||
|
||||
void WriteLE32(uint32_t Value) {
|
||||
WriteLE16(uint16_t(Value >> 0));
|
||||
WriteLE16(uint16_t(Value >> 16));
|
||||
}
|
||||
|
||||
void WriteLE64(uint64_t Value) {
|
||||
WriteLE32(uint32_t(Value >> 0));
|
||||
WriteLE32(uint32_t(Value >> 32));
|
||||
}
|
||||
|
||||
void WriteBE16(uint16_t Value) {
|
||||
Write8(uint8_t(Value >> 8));
|
||||
Write8(uint8_t(Value >> 0));
|
||||
}
|
||||
|
||||
void WriteBE32(uint32_t Value) {
|
||||
WriteBE16(uint16_t(Value >> 16));
|
||||
WriteBE16(uint16_t(Value >> 0));
|
||||
}
|
||||
|
||||
void WriteBE64(uint64_t Value) {
|
||||
WriteBE32(uint32_t(Value >> 32));
|
||||
WriteBE32(uint32_t(Value >> 0));
|
||||
}
|
||||
|
||||
void Write16(uint16_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE16(Value);
|
||||
else
|
||||
WriteBE16(Value);
|
||||
}
|
||||
|
||||
void Write32(uint32_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE32(Value);
|
||||
else
|
||||
WriteBE32(Value);
|
||||
}
|
||||
|
||||
void Write64(uint64_t Value) {
|
||||
if (IsLittleEndian)
|
||||
WriteLE64(Value);
|
||||
else
|
||||
WriteBE64(Value);
|
||||
}
|
||||
|
||||
void WriteZeros(unsigned N) {
|
||||
const char Zeros[16] = { 0 };
|
||||
|
||||
for (unsigned i = 0, e = N / 16; i != e; ++i)
|
||||
OS << StringRef(Zeros, 16);
|
||||
|
||||
OS << StringRef(Zeros, N % 16);
|
||||
}
|
||||
|
||||
void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) {
|
||||
OS << Str;
|
||||
if (ZeroFillSize)
|
||||
WriteZeros(ZeroFillSize - Str.size());
|
||||
}
|
||||
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -291,7 +291,8 @@ class TargetAsmBackend;
|
||||
/// assembler.
|
||||
///
|
||||
/// \param InstPrint - If given, the instruction printer to use. If not given
|
||||
/// the MCInst representation will be printed.
|
||||
/// the MCInst representation will be printed. This method takes ownership of
|
||||
/// InstPrint.
|
||||
///
|
||||
/// \param CE - If given, a code emitter to use to show the instruction
|
||||
/// encoding inline with the assembly.
|
||||
|
@ -28,8 +28,7 @@ namespace llvm {
|
||||
///
|
||||
/// If the symbol is defined/emitted into the current translation unit, the
|
||||
/// Section member is set to indicate what section it lives in. Otherwise, if
|
||||
/// it is a reference to an external entity, it has a null section.
|
||||
///
|
||||
/// it is a reference to an external entity, it has a null section.
|
||||
class MCSymbol {
|
||||
// Special sentinal value for the absolute pseudo section.
|
||||
//
|
||||
@ -52,7 +51,7 @@ namespace llvm {
|
||||
/// typically does not survive in the .o file's symbol table. Usually
|
||||
/// "Lfoo" or ".foo".
|
||||
unsigned IsTemporary : 1;
|
||||
|
||||
|
||||
private: // MCContext creates and uniques these.
|
||||
friend class MCContext;
|
||||
MCSymbol(StringRef name, bool isTemporary)
|
||||
@ -83,6 +82,12 @@ namespace llvm {
|
||||
return Section != 0;
|
||||
}
|
||||
|
||||
/// isInSection - Check if this symbol is defined in some section (i.e., it
|
||||
/// is defined but not absolute).
|
||||
bool isInSection() const {
|
||||
return isDefined() && !isAbsolute();
|
||||
}
|
||||
|
||||
/// isUndefined - Check if this symbol undefined (i.e., implicitly defined).
|
||||
bool isUndefined() const {
|
||||
return !isDefined();
|
||||
@ -96,7 +101,7 @@ namespace llvm {
|
||||
/// getSection - Get the section associated with a defined, non-absolute
|
||||
/// symbol.
|
||||
const MCSection &getSection() const {
|
||||
assert(!isUndefined() && !isAbsolute() && "Invalid accessor!");
|
||||
assert(isInSection() && "Invalid accessor!");
|
||||
return *Section;
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,9 @@
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class MCSymbol;
|
||||
class MCAsmInfo;
|
||||
class MCSymbol;
|
||||
class MCSymbolRefExpr;
|
||||
class raw_ostream;
|
||||
|
||||
/// MCValue - This represents an "assembler immediate". In its most general
|
||||
@ -34,13 +35,13 @@ class raw_ostream;
|
||||
/// Note that this class must remain a simple POD value class, because we need
|
||||
/// it to live in unions etc.
|
||||
class MCValue {
|
||||
const MCSymbol *SymA, *SymB;
|
||||
const MCSymbolRefExpr *SymA, *SymB;
|
||||
int64_t Cst;
|
||||
public:
|
||||
|
||||
int64_t getConstant() const { return Cst; }
|
||||
const MCSymbol *getSymA() const { return SymA; }
|
||||
const MCSymbol *getSymB() const { return SymB; }
|
||||
const MCSymbolRefExpr *getSymA() const { return SymA; }
|
||||
const MCSymbolRefExpr *getSymB() const { return SymB; }
|
||||
|
||||
/// isAbsolute - Is this an absolute (as opposed to relocatable) value.
|
||||
bool isAbsolute() const { return !SymA && !SymB; }
|
||||
@ -57,11 +58,11 @@ class MCValue {
|
||||
|
||||
/// print - Print the value to the stream \arg OS.
|
||||
void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
|
||||
|
||||
|
||||
/// dump - Print the value to stderr.
|
||||
void dump() const;
|
||||
|
||||
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB = 0,
|
||||
static MCValue get(const MCSymbolRefExpr *SymA, const MCSymbolRefExpr *SymB=0,
|
||||
int64_t Val = 0) {
|
||||
MCValue R;
|
||||
assert((!SymB || SymA) && "Invalid relocatable MCValue!");
|
||||
@ -70,7 +71,7 @@ class MCValue {
|
||||
R.SymB = SymB;
|
||||
return R;
|
||||
}
|
||||
|
||||
|
||||
static MCValue get(int64_t Val) {
|
||||
MCValue R;
|
||||
R.Cst = Val;
|
||||
@ -78,7 +79,7 @@ class MCValue {
|
||||
R.SymB = 0;
|
||||
return R;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
43
include/llvm/MC/MachObjectWriter.h
Normal file
43
include/llvm/MC/MachObjectWriter.h
Normal file
@ -0,0 +1,43 @@
|
||||
//===-- llvm/MC/MachObjectWriter.h - Mach-O File Writer ---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_MC_MACHOBJECTWRITER_H
|
||||
#define LLVM_MC_MACHOBJECTWRITER_H
|
||||
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmFixup;
|
||||
class MCAssembler;
|
||||
class MCDataFragment;
|
||||
class MCValue;
|
||||
class raw_ostream;
|
||||
|
||||
class MachObjectWriter : public MCObjectWriter {
|
||||
void *Impl;
|
||||
|
||||
public:
|
||||
MachObjectWriter(raw_ostream &OS, bool Is64Bit, bool IsLittleEndian = true);
|
||||
virtual ~MachObjectWriter();
|
||||
|
||||
virtual void ExecutePostLayoutBinding(MCAssembler &Asm);
|
||||
|
||||
virtual void RecordRelocation(const MCAssembler &Asm,
|
||||
const MCDataFragment &Fragment,
|
||||
const MCAsmFixup &Fixup, MCValue Target,
|
||||
uint64_t &FixedValue);
|
||||
|
||||
virtual void WriteObject(const MCAssembler &Asm);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
@ -15,9 +15,12 @@
|
||||
#define LLVM_SUPPORT_ALLOCATOR_H
|
||||
|
||||
#include "llvm/Support/AlignOf.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -175,4 +178,22 @@ class BumpPtrAllocator {
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
inline void *operator new(size_t Size, llvm::BumpPtrAllocator &Allocator) {
|
||||
struct S {
|
||||
char c;
|
||||
#ifdef __GNUC__
|
||||
char x __attribute__((aligned));
|
||||
#else
|
||||
union {
|
||||
double D;
|
||||
long double LD;
|
||||
long long L;
|
||||
void *P;
|
||||
} x;
|
||||
#endif
|
||||
};
|
||||
return Allocator.Allocate(Size, std::min((size_t)llvm::NextPowerOf2(Size),
|
||||
offsetof(S, x)));
|
||||
}
|
||||
|
||||
#endif // LLVM_SUPPORT_ALLOCATOR_H
|
||||
|
@ -56,4 +56,11 @@ class RecyclingAllocator {
|
||||
|
||||
}
|
||||
|
||||
template<class AllocatorType, class T, size_t Size, size_t Align>
|
||||
inline void *operator new(size_t,
|
||||
llvm::RecyclingAllocator<AllocatorType,
|
||||
T, Size, Align> &Allocator) {
|
||||
return Allocator.Allocate();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -389,66 +389,66 @@ class InstrInfo {
|
||||
// Standard Pseudo Instructions.
|
||||
let isCodeGenOnly = 1 in {
|
||||
def PHI : Instruction {
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops variable_ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins variable_ops);
|
||||
let AsmString = "PHINODE";
|
||||
let Namespace = "TargetOpcode";
|
||||
}
|
||||
def INLINEASM : Instruction {
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops variable_ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins variable_ops);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
}
|
||||
def DBG_LABEL : Instruction {
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops i32imm:$id);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins i32imm:$id);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let hasCtrlDep = 1;
|
||||
let isNotDuplicable = 1;
|
||||
}
|
||||
def EH_LABEL : Instruction {
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops i32imm:$id);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins i32imm:$id);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let hasCtrlDep = 1;
|
||||
let isNotDuplicable = 1;
|
||||
}
|
||||
def GC_LABEL : Instruction {
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops i32imm:$id);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins i32imm:$id);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let hasCtrlDep = 1;
|
||||
let isNotDuplicable = 1;
|
||||
}
|
||||
def KILL : Instruction {
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops variable_ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins variable_ops);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let neverHasSideEffects = 1;
|
||||
}
|
||||
def EXTRACT_SUBREG : Instruction {
|
||||
let OutOperandList = (ops unknown:$dst);
|
||||
let InOperandList = (ops unknown:$supersrc, i32imm:$subidx);
|
||||
let OutOperandList = (outs unknown:$dst);
|
||||
let InOperandList = (ins unknown:$supersrc, i32imm:$subidx);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let neverHasSideEffects = 1;
|
||||
}
|
||||
def INSERT_SUBREG : Instruction {
|
||||
let OutOperandList = (ops unknown:$dst);
|
||||
let InOperandList = (ops unknown:$supersrc, unknown:$subsrc, i32imm:$subidx);
|
||||
let OutOperandList = (outs unknown:$dst);
|
||||
let InOperandList = (ins unknown:$supersrc, unknown:$subsrc, i32imm:$subidx);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let neverHasSideEffects = 1;
|
||||
let Constraints = "$supersrc = $dst";
|
||||
}
|
||||
def IMPLICIT_DEF : Instruction {
|
||||
let OutOperandList = (ops unknown:$dst);
|
||||
let InOperandList = (ops);
|
||||
let OutOperandList = (outs unknown:$dst);
|
||||
let InOperandList = (ins);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let neverHasSideEffects = 1;
|
||||
@ -456,23 +456,23 @@ def IMPLICIT_DEF : Instruction {
|
||||
let isAsCheapAsAMove = 1;
|
||||
}
|
||||
def SUBREG_TO_REG : Instruction {
|
||||
let OutOperandList = (ops unknown:$dst);
|
||||
let InOperandList = (ops unknown:$implsrc, unknown:$subsrc, i32imm:$subidx);
|
||||
let OutOperandList = (outs unknown:$dst);
|
||||
let InOperandList = (ins unknown:$implsrc, unknown:$subsrc, i32imm:$subidx);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let neverHasSideEffects = 1;
|
||||
}
|
||||
def COPY_TO_REGCLASS : Instruction {
|
||||
let OutOperandList = (ops unknown:$dst);
|
||||
let InOperandList = (ops unknown:$src, i32imm:$regclass);
|
||||
let OutOperandList = (outs unknown:$dst);
|
||||
let InOperandList = (ins unknown:$src, i32imm:$regclass);
|
||||
let AsmString = "";
|
||||
let Namespace = "TargetOpcode";
|
||||
let neverHasSideEffects = 1;
|
||||
let isAsCheapAsAMove = 1;
|
||||
}
|
||||
def DBG_VALUE : Instruction {
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops variable_ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins variable_ops);
|
||||
let AsmString = "DBG_VALUE";
|
||||
let Namespace = "TargetOpcode";
|
||||
let isAsCheapAsAMove = 1;
|
||||
@ -491,6 +491,11 @@ class AsmParser {
|
||||
// class. Generated AsmParser classes are always prefixed with the target
|
||||
// name.
|
||||
string AsmParserClassName = "AsmParser";
|
||||
|
||||
// AsmParserInstCleanup - If non-empty, this is the name of a custom function on the
|
||||
// AsmParser class to call on every matched instruction. This can be used to
|
||||
// perform target specific instruction post-processing.
|
||||
string AsmParserInstCleanup = "";
|
||||
|
||||
// Variant - AsmParsers can be of multiple different variants. Variants are
|
||||
// used to support targets that need to parser multiple formats for the
|
||||
|
@ -10,9 +10,15 @@
|
||||
#ifndef LLVM_TARGET_TARGETASMBACKEND_H
|
||||
#define LLVM_TARGET_TARGETASMBACKEND_H
|
||||
|
||||
#include "llvm/System/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
class MCAsmFixup;
|
||||
class MCDataFragment;
|
||||
class MCObjectWriter;
|
||||
class MCSection;
|
||||
class Target;
|
||||
class raw_ostream;
|
||||
|
||||
/// TargetAsmBackend - Generic interface to target specific assembler backends.
|
||||
class TargetAsmBackend {
|
||||
@ -24,11 +30,19 @@ class TargetAsmBackend {
|
||||
/// TheTarget - The Target that this machine was created for.
|
||||
const Target &TheTarget;
|
||||
|
||||
unsigned HasAbsolutizedSet : 1;
|
||||
unsigned HasReliableSymbolDifference : 1;
|
||||
unsigned HasScatteredSymbols : 1;
|
||||
|
||||
public:
|
||||
virtual ~TargetAsmBackend();
|
||||
|
||||
const Target &getTarget() const { return TheTarget; }
|
||||
|
||||
/// createObjectWriter - Create a new MCObjectWriter instance for use by the
|
||||
/// assembler backend to emit the final object file.
|
||||
virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0;
|
||||
|
||||
/// hasAbsolutizedSet - Check whether this target "absolutizes"
|
||||
/// assignments. That is, given code like:
|
||||
/// a:
|
||||
@ -40,7 +54,21 @@ class TargetAsmBackend {
|
||||
/// value of L0 - L1. This distinction is only relevant for platforms that
|
||||
/// support scattered symbols, since in the absence of scattered symbols (a -
|
||||
/// b) cannot change after assembly.
|
||||
virtual bool hasAbsolutizedSet() const { return false; }
|
||||
bool hasAbsolutizedSet() const { return HasAbsolutizedSet; }
|
||||
|
||||
/// hasReliableSymbolDifference - Check whether this target implements
|
||||
/// accurate relocations for differences between symbols. If not, differences
|
||||
/// between symbols will always be relocatable expressions and any references
|
||||
/// to temporary symbols will be assumed to be in the same atom, unless they
|
||||
/// reside in a different section.
|
||||
///
|
||||
/// This should always be true (since it results in fewer relocations with no
|
||||
/// loss of functionality), but is currently supported as a way to maintain
|
||||
/// exact object compatibility with Darwin 'as' (on non-x86_64). It should
|
||||
/// eventually should be eliminated. See also \see hasAbsolutizedSet.
|
||||
bool hasReliableSymbolDifference() const {
|
||||
return HasReliableSymbolDifference;
|
||||
}
|
||||
|
||||
/// hasScatteredSymbols - Check whether this target supports scattered
|
||||
/// symbols. If so, the assembler should assume that atoms can be scattered by
|
||||
@ -50,13 +78,23 @@ class TargetAsmBackend {
|
||||
///
|
||||
/// Note that the assembler currently does not reason about atoms, instead it
|
||||
/// assumes all temporary symbols reside in the "current atom".
|
||||
virtual bool hasScatteredSymbols() const { return false; }
|
||||
bool hasScatteredSymbols() const { return HasScatteredSymbols; }
|
||||
|
||||
/// doesSectionRequireSymbols - Check whether the given section requires that
|
||||
/// all symbols (even temporaries) have symbol table entries.
|
||||
virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// isVirtualSection - Check whether the given section is "virtual", that is
|
||||
/// has no actual object file contents.
|
||||
virtual bool isVirtualSection(const MCSection &Section) const = 0;
|
||||
|
||||
/// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided
|
||||
/// data fragment, at the offset specified by the fixup and following the
|
||||
/// fixup kind as appropriate.
|
||||
virtual void ApplyFixup(const MCAsmFixup &Fixup, MCDataFragment &Fragment,
|
||||
uint64_t Value) const = 0;
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -307,7 +307,7 @@ class TargetLowering {
|
||||
/// intrinsic will need to map to a MemIntrinsicNode (touches memory). If
|
||||
/// this is the case, it returns true and store the intrinsic
|
||||
/// information into the IntrinsicInfo that was passed to the function.
|
||||
typedef struct IntrinsicInfo {
|
||||
struct IntrinsicInfo {
|
||||
unsigned opc; // target opcode
|
||||
EVT memVT; // memory VT
|
||||
const Value* ptrVal; // value representing memory location
|
||||
@ -316,9 +316,9 @@ class TargetLowering {
|
||||
bool vol; // is volatile?
|
||||
bool readMem; // reads memory?
|
||||
bool writeMem; // writes memory?
|
||||
} IntrinisicInfo;
|
||||
};
|
||||
|
||||
virtual bool getTgtMemIntrinsic(IntrinsicInfo& Info,
|
||||
virtual bool getTgtMemIntrinsic(IntrinsicInfo &Info,
|
||||
CallInst &I, unsigned Intrinsic) {
|
||||
return false;
|
||||
}
|
||||
|
@ -144,11 +144,6 @@ namespace llvm {
|
||||
/// wth earlier copy coalescing.
|
||||
extern bool StrongPHIElim;
|
||||
|
||||
/// DisableScheduling - This flag disables instruction scheduling. In
|
||||
/// particular, it assigns an ordering to the SDNodes, which the scheduler
|
||||
/// uses instead of its normal heuristics to perform scheduling.
|
||||
extern bool DisableScheduling;
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -55,7 +55,7 @@ namespace llvm {
|
||||
|
||||
typedef unsigned (*TripleMatchQualityFnTy)(const std::string &TT);
|
||||
|
||||
typedef const MCAsmInfo *(*AsmInfoCtorFnTy)(const Target &T,
|
||||
typedef MCAsmInfo *(*AsmInfoCtorFnTy)(const Target &T,
|
||||
StringRef TT);
|
||||
typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T,
|
||||
const std::string &TT,
|
||||
@ -68,7 +68,7 @@ namespace llvm {
|
||||
typedef TargetAsmLexer *(*AsmLexerCtorTy)(const Target &T,
|
||||
const MCAsmInfo &MAI);
|
||||
typedef TargetAsmParser *(*AsmParserCtorTy)(const Target &T,MCAsmParser &P);
|
||||
typedef const MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T);
|
||||
typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T);
|
||||
typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T,
|
||||
unsigned SyntaxVariant,
|
||||
const MCAsmInfo &MAI,
|
||||
@ -184,7 +184,7 @@ namespace llvm {
|
||||
/// feature set; it should always be provided. Generally this should be
|
||||
/// either the target triple from the module, or the target triple of the
|
||||
/// host if that does not exist.
|
||||
const MCAsmInfo *createAsmInfo(StringRef Triple) const {
|
||||
MCAsmInfo *createAsmInfo(StringRef Triple) const {
|
||||
if (!AsmInfoCtorFn)
|
||||
return 0;
|
||||
return AsmInfoCtorFn(*this, Triple);
|
||||
@ -241,7 +241,7 @@ namespace llvm {
|
||||
return AsmPrinterCtorFn(OS, TM, Streamer);
|
||||
}
|
||||
|
||||
const MCDisassembler *createMCDisassembler() const {
|
||||
MCDisassembler *createMCDisassembler() const {
|
||||
if (!MCDisassemblerCtorFn)
|
||||
return 0;
|
||||
return MCDisassemblerCtorFn(*this);
|
||||
@ -529,7 +529,7 @@ namespace llvm {
|
||||
TargetRegistry::RegisterAsmInfo(T, &Allocator);
|
||||
}
|
||||
private:
|
||||
static const MCAsmInfo *Allocator(const Target &T, StringRef TT) {
|
||||
static MCAsmInfo *Allocator(const Target &T, StringRef TT) {
|
||||
return new MCAsmInfoImpl(T, TT);
|
||||
}
|
||||
|
||||
|
@ -219,6 +219,7 @@ def SDNPMayStore : SDNodeProperty; // May write to memory, sets 'mayStore'.
|
||||
def SDNPMayLoad : SDNodeProperty; // May read memory, sets 'mayLoad'.
|
||||
def SDNPSideEffect : SDNodeProperty; // Sets 'HasUnmodelledSideEffects'.
|
||||
def SDNPMemOperand : SDNodeProperty; // Touches memory, has assoc MemOperand
|
||||
def SDNPVariadic : SDNodeProperty; // Node has variable arguments.
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Selection DAG Node definitions.
|
||||
|
@ -564,21 +564,6 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps,
|
||||
|
||||
unsigned BitWidth =
|
||||
TD->getTypeSizeInBits(TD->getIntPtrType(Ptr->getContext()));
|
||||
APInt BasePtr(BitWidth, 0);
|
||||
bool BaseIsInt = true;
|
||||
if (!Ptr->isNullValue()) {
|
||||
// If this is a inttoptr from a constant int, we can fold this as the base,
|
||||
// otherwise we can't.
|
||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
|
||||
if (CE->getOpcode() == Instruction::IntToPtr)
|
||||
if (ConstantInt *Base = dyn_cast<ConstantInt>(CE->getOperand(0))) {
|
||||
BasePtr = Base->getValue();
|
||||
BasePtr.zextOrTrunc(BitWidth);
|
||||
}
|
||||
|
||||
if (BasePtr == 0)
|
||||
BaseIsInt = false;
|
||||
}
|
||||
|
||||
// If this is a constant expr gep that is effectively computing an
|
||||
// "offsetof", fold it into 'cast int Size to T*' instead of 'gep 0, 0, 12'
|
||||
@ -615,7 +600,14 @@ static Constant *SymbolicallyEvaluateGEP(Constant *const *Ops, unsigned NumOps,
|
||||
|
||||
// If the base value for this address is a literal integer value, fold the
|
||||
// getelementptr to the resulting integer value casted to the pointer type.
|
||||
if (BaseIsInt) {
|
||||
APInt BasePtr(BitWidth, 0);
|
||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Ptr))
|
||||
if (CE->getOpcode() == Instruction::IntToPtr)
|
||||
if (ConstantInt *Base = dyn_cast<ConstantInt>(CE->getOperand(0))) {
|
||||
BasePtr = Base->getValue();
|
||||
BasePtr.zextOrTrunc(BitWidth);
|
||||
}
|
||||
if (Ptr->isNullValue() || BasePtr != 0) {
|
||||
Constant *C = ConstantInt::get(Ptr->getContext(), Offset+BasePtr);
|
||||
return ConstantExpr::getIntToPtr(C, ResultTy);
|
||||
}
|
||||
@ -1002,6 +994,8 @@ llvm::canConstantFoldCallTo(const Function *F) {
|
||||
case Intrinsic::usub_with_overflow:
|
||||
case Intrinsic::sadd_with_overflow:
|
||||
case Intrinsic::ssub_with_overflow:
|
||||
case Intrinsic::convert_from_fp16:
|
||||
case Intrinsic::convert_to_fp16:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -1082,6 +1076,15 @@ llvm::ConstantFoldCall(Function *F,
|
||||
const Type *Ty = F->getReturnType();
|
||||
if (NumOperands == 1) {
|
||||
if (ConstantFP *Op = dyn_cast<ConstantFP>(Operands[0])) {
|
||||
if (Name == "llvm.convert.to.fp16") {
|
||||
APFloat Val(Op->getValueAPF());
|
||||
|
||||
bool lost = false;
|
||||
Val.convert(APFloat::IEEEhalf, APFloat::rmNearestTiesToEven, &lost);
|
||||
|
||||
return ConstantInt::get(F->getContext(), Val.bitcastToAPInt());
|
||||
}
|
||||
|
||||
if (!Ty->isFloatTy() && !Ty->isDoubleTy())
|
||||
return 0;
|
||||
/// Currently APFloat versions of these functions do not exist, so we use
|
||||
@ -1166,6 +1169,20 @@ llvm::ConstantFoldCall(Function *F,
|
||||
return ConstantInt::get(Ty, Op->getValue().countTrailingZeros());
|
||||
else if (Name.startswith("llvm.ctlz"))
|
||||
return ConstantInt::get(Ty, Op->getValue().countLeadingZeros());
|
||||
else if (Name == "llvm.convert.from.fp16") {
|
||||
APFloat Val(Op->getValue());
|
||||
|
||||
bool lost = false;
|
||||
APFloat::opStatus status =
|
||||
Val.convert(APFloat::IEEEsingle, APFloat::rmNearestTiesToEven, &lost);
|
||||
|
||||
// Conversion is always precise.
|
||||
status = status;
|
||||
assert(status == APFloat::opOK && !lost &&
|
||||
"Precision lost during fp16 constfolding");
|
||||
|
||||
return ConstantFP::get(F->getContext(), Val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -119,8 +119,7 @@ bool LoopDependenceAnalysis::findOrInsertDependencePair(Value *A,
|
||||
P = Pairs.FindNodeOrInsertPos(id, insertPos);
|
||||
if (P) return true;
|
||||
|
||||
P = PairAllocator.Allocate<DependencePair>();
|
||||
new (P) DependencePair(id, A, B);
|
||||
P = new (PairAllocator) DependencePair(id, A, B);
|
||||
Pairs.InsertNode(P, insertPos);
|
||||
return false;
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ bool SCEV::isAllOnesValue() const {
|
||||
}
|
||||
|
||||
SCEVCouldNotCompute::SCEVCouldNotCompute() :
|
||||
SCEV(FoldingSetNodeID(), scCouldNotCompute) {}
|
||||
SCEV(FoldingSetNodeIDRef(), scCouldNotCompute) {}
|
||||
|
||||
bool SCEVCouldNotCompute::isLoopInvariant(const Loop *L) const {
|
||||
llvm_unreachable("Attempt to use a SCEVCouldNotCompute object!");
|
||||
@ -177,8 +177,7 @@ const SCEV *ScalarEvolution::getConstant(ConstantInt *V) {
|
||||
ID.AddPointer(V);
|
||||
void *IP = 0;
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
|
||||
SCEV *S = SCEVAllocator.Allocate<SCEVConstant>();
|
||||
new (S) SCEVConstant(ID, V);
|
||||
SCEV *S = new (SCEVAllocator) SCEVConstant(ID.Intern(SCEVAllocator), V);
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
return S;
|
||||
}
|
||||
@ -199,7 +198,7 @@ void SCEVConstant::print(raw_ostream &OS) const {
|
||||
WriteAsOperand(OS, V, false);
|
||||
}
|
||||
|
||||
SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeID &ID,
|
||||
SCEVCastExpr::SCEVCastExpr(const FoldingSetNodeIDRef ID,
|
||||
unsigned SCEVTy, const SCEV *op, const Type *ty)
|
||||
: SCEV(ID, SCEVTy), Op(op), Ty(ty) {}
|
||||
|
||||
@ -211,7 +210,7 @@ bool SCEVCastExpr::properlyDominates(BasicBlock *BB, DominatorTree *DT) const {
|
||||
return Op->properlyDominates(BB, DT);
|
||||
}
|
||||
|
||||
SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeID &ID,
|
||||
SCEVTruncateExpr::SCEVTruncateExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, const Type *ty)
|
||||
: SCEVCastExpr(ID, scTruncate, op, ty) {
|
||||
assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) &&
|
||||
@ -223,7 +222,7 @@ void SCEVTruncateExpr::print(raw_ostream &OS) const {
|
||||
OS << "(trunc " << *Op->getType() << " " << *Op << " to " << *Ty << ")";
|
||||
}
|
||||
|
||||
SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeID &ID,
|
||||
SCEVZeroExtendExpr::SCEVZeroExtendExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, const Type *ty)
|
||||
: SCEVCastExpr(ID, scZeroExtend, op, ty) {
|
||||
assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) &&
|
||||
@ -235,7 +234,7 @@ void SCEVZeroExtendExpr::print(raw_ostream &OS) const {
|
||||
OS << "(zext " << *Op->getType() << " " << *Op << " to " << *Ty << ")";
|
||||
}
|
||||
|
||||
SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeID &ID,
|
||||
SCEVSignExtendExpr::SCEVSignExtendExpr(const FoldingSetNodeIDRef ID,
|
||||
const SCEV *op, const Type *ty)
|
||||
: SCEVCastExpr(ID, scSignExtend, op, ty) {
|
||||
assert((Op->getType()->isIntegerTy() || Op->getType()->isPointerTy()) &&
|
||||
@ -248,10 +247,10 @@ void SCEVSignExtendExpr::print(raw_ostream &OS) const {
|
||||
}
|
||||
|
||||
void SCEVCommutativeExpr::print(raw_ostream &OS) const {
|
||||
assert(Operands.size() > 1 && "This plus expr shouldn't exist!");
|
||||
assert(NumOperands > 1 && "This plus expr shouldn't exist!");
|
||||
const char *OpStr = getOperationStr();
|
||||
OS << "(" << *Operands[0];
|
||||
for (unsigned i = 1, e = Operands.size(); i != e; ++i)
|
||||
for (unsigned i = 1, e = NumOperands; i != e; ++i)
|
||||
OS << OpStr << *Operands[i];
|
||||
OS << ")";
|
||||
}
|
||||
@ -329,7 +328,7 @@ SCEVAddRecExpr::properlyDominates(BasicBlock *BB, DominatorTree *DT) const {
|
||||
|
||||
void SCEVAddRecExpr::print(raw_ostream &OS) const {
|
||||
OS << "{" << *Operands[0];
|
||||
for (unsigned i = 1, e = Operands.size(); i != e; ++i)
|
||||
for (unsigned i = 1, e = NumOperands; i != e; ++i)
|
||||
OS << ",+," << *Operands[i];
|
||||
OS << "}<";
|
||||
WriteAsOperand(OS, L->getHeader(), /*PrintType=*/false);
|
||||
@ -846,8 +845,8 @@ const SCEV *ScalarEvolution::getTruncateExpr(const SCEV *Op,
|
||||
// The cast wasn't folded; create an explicit cast node.
|
||||
// Recompute the insert position, as it may have been invalidated.
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
|
||||
SCEV *S = SCEVAllocator.Allocate<SCEVTruncateExpr>();
|
||||
new (S) SCEVTruncateExpr(ID, Op, Ty);
|
||||
SCEV *S = new (SCEVAllocator) SCEVTruncateExpr(ID.Intern(SCEVAllocator),
|
||||
Op, Ty);
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
return S;
|
||||
}
|
||||
@ -981,8 +980,8 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op,
|
||||
// The cast wasn't folded; create an explicit cast node.
|
||||
// Recompute the insert position, as it may have been invalidated.
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
|
||||
SCEV *S = SCEVAllocator.Allocate<SCEVZeroExtendExpr>();
|
||||
new (S) SCEVZeroExtendExpr(ID, Op, Ty);
|
||||
SCEV *S = new (SCEVAllocator) SCEVZeroExtendExpr(ID.Intern(SCEVAllocator),
|
||||
Op, Ty);
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
return S;
|
||||
}
|
||||
@ -1116,8 +1115,8 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
|
||||
// The cast wasn't folded; create an explicit cast node.
|
||||
// Recompute the insert position, as it may have been invalidated.
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
|
||||
SCEV *S = SCEVAllocator.Allocate<SCEVSignExtendExpr>();
|
||||
new (S) SCEVSignExtendExpr(ID, Op, Ty);
|
||||
SCEV *S = new (SCEVAllocator) SCEVSignExtendExpr(ID.Intern(SCEVAllocator),
|
||||
Op, Ty);
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
return S;
|
||||
}
|
||||
@ -1202,23 +1201,23 @@ static bool
|
||||
CollectAddOperandsWithScales(DenseMap<const SCEV *, APInt> &M,
|
||||
SmallVector<const SCEV *, 8> &NewOps,
|
||||
APInt &AccumulatedConstant,
|
||||
const SmallVectorImpl<const SCEV *> &Ops,
|
||||
const SCEV *const *Ops, size_t NumOperands,
|
||||
const APInt &Scale,
|
||||
ScalarEvolution &SE) {
|
||||
bool Interesting = false;
|
||||
|
||||
// Iterate over the add operands.
|
||||
for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
|
||||
for (unsigned i = 0, e = NumOperands; i != e; ++i) {
|
||||
const SCEVMulExpr *Mul = dyn_cast<SCEVMulExpr>(Ops[i]);
|
||||
if (Mul && isa<SCEVConstant>(Mul->getOperand(0))) {
|
||||
APInt NewScale =
|
||||
Scale * cast<SCEVConstant>(Mul->getOperand(0))->getValue()->getValue();
|
||||
if (Mul->getNumOperands() == 2 && isa<SCEVAddExpr>(Mul->getOperand(1))) {
|
||||
// A multiplication of a constant with another add; recurse.
|
||||
const SCEVAddExpr *Add = cast<SCEVAddExpr>(Mul->getOperand(1));
|
||||
Interesting |=
|
||||
CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant,
|
||||
cast<SCEVAddExpr>(Mul->getOperand(1))
|
||||
->getOperands(),
|
||||
Add->op_begin(), Add->getNumOperands(),
|
||||
NewScale, SE);
|
||||
} else {
|
||||
// A multiplication of a constant with some other value. Update
|
||||
@ -1427,7 +1426,8 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
|
||||
SmallVector<const SCEV *, 8> NewOps;
|
||||
APInt AccumulatedConstant(BitWidth, 0);
|
||||
if (CollectAddOperandsWithScales(M, NewOps, AccumulatedConstant,
|
||||
Ops, APInt(BitWidth, 1), *this)) {
|
||||
Ops.data(), Ops.size(),
|
||||
APInt(BitWidth, 1), *this)) {
|
||||
// Some interesting folding opportunity is present, so its worthwhile to
|
||||
// re-generate the operands list. Group the operands by constant scale,
|
||||
// to avoid multiplying by the same constant scale multiple times.
|
||||
@ -1611,8 +1611,10 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
|
||||
SCEVAddExpr *S =
|
||||
static_cast<SCEVAddExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
|
||||
if (!S) {
|
||||
S = SCEVAllocator.Allocate<SCEVAddExpr>();
|
||||
new (S) SCEVAddExpr(ID, Ops);
|
||||
const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
|
||||
std::uninitialized_copy(Ops.begin(), Ops.end(), O);
|
||||
S = new (SCEVAllocator) SCEVAddExpr(ID.Intern(SCEVAllocator),
|
||||
O, Ops.size());
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
}
|
||||
if (HasNUW) S->setHasNoUnsignedWrap(true);
|
||||
@ -1819,8 +1821,10 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
|
||||
SCEVMulExpr *S =
|
||||
static_cast<SCEVMulExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
|
||||
if (!S) {
|
||||
S = SCEVAllocator.Allocate<SCEVMulExpr>();
|
||||
new (S) SCEVMulExpr(ID, Ops);
|
||||
const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
|
||||
std::uninitialized_copy(Ops.begin(), Ops.end(), O);
|
||||
S = new (SCEVAllocator) SCEVMulExpr(ID.Intern(SCEVAllocator),
|
||||
O, Ops.size());
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
}
|
||||
if (HasNUW) S->setHasNoUnsignedWrap(true);
|
||||
@ -1880,9 +1884,7 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
|
||||
const SCEV *Op = M->getOperand(i);
|
||||
const SCEV *Div = getUDivExpr(Op, RHSC);
|
||||
if (!isa<SCEVUDivExpr>(Div) && getMulExpr(Div, RHSC) == Op) {
|
||||
const SmallVectorImpl<const SCEV *> &MOperands = M->getOperands();
|
||||
Operands = SmallVector<const SCEV *, 4>(MOperands.begin(),
|
||||
MOperands.end());
|
||||
Operands = SmallVector<const SCEV *, 4>(M->op_begin(), M->op_end());
|
||||
Operands[i] = Div;
|
||||
return getMulExpr(Operands);
|
||||
}
|
||||
@ -1921,8 +1923,8 @@ const SCEV *ScalarEvolution::getUDivExpr(const SCEV *LHS,
|
||||
ID.AddPointer(RHS);
|
||||
void *IP = 0;
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
|
||||
SCEV *S = SCEVAllocator.Allocate<SCEVUDivExpr>();
|
||||
new (S) SCEVUDivExpr(ID, LHS, RHS);
|
||||
SCEV *S = new (SCEVAllocator) SCEVUDivExpr(ID.Intern(SCEVAllocator),
|
||||
LHS, RHS);
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
return S;
|
||||
}
|
||||
@ -2030,8 +2032,10 @@ ScalarEvolution::getAddRecExpr(SmallVectorImpl<const SCEV *> &Operands,
|
||||
SCEVAddRecExpr *S =
|
||||
static_cast<SCEVAddRecExpr *>(UniqueSCEVs.FindNodeOrInsertPos(ID, IP));
|
||||
if (!S) {
|
||||
S = SCEVAllocator.Allocate<SCEVAddRecExpr>();
|
||||
new (S) SCEVAddRecExpr(ID, Operands, L);
|
||||
const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Operands.size());
|
||||
std::uninitialized_copy(Operands.begin(), Operands.end(), O);
|
||||
S = new (SCEVAllocator) SCEVAddRecExpr(ID.Intern(SCEVAllocator),
|
||||
O, Operands.size(), L);
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
}
|
||||
if (HasNUW) S->setHasNoUnsignedWrap(true);
|
||||
@ -2130,8 +2134,10 @@ ScalarEvolution::getSMaxExpr(SmallVectorImpl<const SCEV *> &Ops) {
|
||||
ID.AddPointer(Ops[i]);
|
||||
void *IP = 0;
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
|
||||
SCEV *S = SCEVAllocator.Allocate<SCEVSMaxExpr>();
|
||||
new (S) SCEVSMaxExpr(ID, Ops);
|
||||
const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
|
||||
std::uninitialized_copy(Ops.begin(), Ops.end(), O);
|
||||
SCEV *S = new (SCEVAllocator) SCEVSMaxExpr(ID.Intern(SCEVAllocator),
|
||||
O, Ops.size());
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
return S;
|
||||
}
|
||||
@ -2227,8 +2233,10 @@ ScalarEvolution::getUMaxExpr(SmallVectorImpl<const SCEV *> &Ops) {
|
||||
ID.AddPointer(Ops[i]);
|
||||
void *IP = 0;
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
|
||||
SCEV *S = SCEVAllocator.Allocate<SCEVUMaxExpr>();
|
||||
new (S) SCEVUMaxExpr(ID, Ops);
|
||||
const SCEV **O = SCEVAllocator.Allocate<const SCEV *>(Ops.size());
|
||||
std::uninitialized_copy(Ops.begin(), Ops.end(), O);
|
||||
SCEV *S = new (SCEVAllocator) SCEVUMaxExpr(ID.Intern(SCEVAllocator),
|
||||
O, Ops.size());
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
return S;
|
||||
}
|
||||
@ -2290,8 +2298,7 @@ const SCEV *ScalarEvolution::getUnknown(Value *V) {
|
||||
ID.AddPointer(V);
|
||||
void *IP = 0;
|
||||
if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S;
|
||||
SCEV *S = SCEVAllocator.Allocate<SCEVUnknown>();
|
||||
new (S) SCEVUnknown(ID, V);
|
||||
SCEV *S = new (SCEVAllocator) SCEVUnknown(ID.Intern(SCEVAllocator), V);
|
||||
UniqueSCEVs.InsertNode(S, IP);
|
||||
return S;
|
||||
}
|
||||
|
@ -232,9 +232,7 @@ static bool FactorOutConstant(const SCEV *&S,
|
||||
const SCEVConstant *FC = cast<SCEVConstant>(Factor);
|
||||
if (const SCEVConstant *C = dyn_cast<SCEVConstant>(M->getOperand(0)))
|
||||
if (!C->getValue()->getValue().srem(FC->getValue()->getValue())) {
|
||||
const SmallVectorImpl<const SCEV *> &MOperands = M->getOperands();
|
||||
SmallVector<const SCEV *, 4> NewMulOps(MOperands.begin(),
|
||||
MOperands.end());
|
||||
SmallVector<const SCEV *, 4> NewMulOps(M->op_begin(), M->op_end());
|
||||
NewMulOps[0] =
|
||||
SE.getConstant(C->getValue()->getValue().sdiv(
|
||||
FC->getValue()->getValue()));
|
||||
@ -249,9 +247,7 @@ static bool FactorOutConstant(const SCEV *&S,
|
||||
const SCEV *Remainder = SE.getIntegerSCEV(0, SOp->getType());
|
||||
if (FactorOutConstant(SOp, Remainder, Factor, SE, TD) &&
|
||||
Remainder->isZero()) {
|
||||
const SmallVectorImpl<const SCEV *> &MOperands = M->getOperands();
|
||||
SmallVector<const SCEV *, 4> NewMulOps(MOperands.begin(),
|
||||
MOperands.end());
|
||||
SmallVector<const SCEV *, 4> NewMulOps(M->op_begin(), M->op_end());
|
||||
NewMulOps[i] = SOp;
|
||||
S = SE.getMulExpr(NewMulOps);
|
||||
return true;
|
||||
@ -297,13 +293,11 @@ static void SimplifyAddOperands(SmallVectorImpl<const SCEV *> &Ops,
|
||||
SE.getAddExpr(NoAddRecs);
|
||||
// If it returned an add, use the operands. Otherwise it simplified
|
||||
// the sum into a single value, so just use that.
|
||||
Ops.clear();
|
||||
if (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Sum))
|
||||
Ops = Add->getOperands();
|
||||
else {
|
||||
Ops.clear();
|
||||
if (!Sum->isZero())
|
||||
Ops.push_back(Sum);
|
||||
}
|
||||
Ops.insert(Ops.end(), Add->op_begin(), Add->op_end());
|
||||
else if (!Sum->isZero())
|
||||
Ops.push_back(Sum);
|
||||
// Then append the addrecs.
|
||||
Ops.insert(Ops.end(), AddRecs.begin(), AddRecs.end());
|
||||
}
|
||||
@ -1060,10 +1054,9 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
|
||||
if (CanonicalIV &&
|
||||
SE.getTypeSizeInBits(CanonicalIV->getType()) >
|
||||
SE.getTypeSizeInBits(Ty)) {
|
||||
const SmallVectorImpl<const SCEV *> &Ops = S->getOperands();
|
||||
SmallVector<const SCEV *, 4> NewOps(Ops.size());
|
||||
for (unsigned i = 0, e = Ops.size(); i != e; ++i)
|
||||
NewOps[i] = SE.getAnyExtendExpr(Ops[i], CanonicalIV->getType());
|
||||
SmallVector<const SCEV *, 4> NewOps(S->getNumOperands());
|
||||
for (unsigned i = 0, e = S->getNumOperands(); i != e; ++i)
|
||||
NewOps[i] = SE.getAnyExtendExpr(S->op_begin()[i], CanonicalIV->getType());
|
||||
Value *V = expand(SE.getAddRecExpr(NewOps, S->getLoop()));
|
||||
BasicBlock *SaveInsertBB = Builder.GetInsertBlock();
|
||||
BasicBlock::iterator SaveInsertPt = Builder.GetInsertPoint();
|
||||
@ -1078,8 +1071,7 @@ Value *SCEVExpander::visitAddRecExpr(const SCEVAddRecExpr *S) {
|
||||
|
||||
// {X,+,F} --> X + {0,+,F}
|
||||
if (!S->getStart()->isZero()) {
|
||||
const SmallVectorImpl<const SCEV *> &SOperands = S->getOperands();
|
||||
SmallVector<const SCEV *, 4> NewOps(SOperands.begin(), SOperands.end());
|
||||
SmallVector<const SCEV *, 4> NewOps(S->op_begin(), S->op_end());
|
||||
NewOps[0] = SE.getIntegerSCEV(0, Ty);
|
||||
const SCEV *Rest = SE.getAddRecExpr(NewOps, L);
|
||||
|
||||
@ -1248,6 +1240,15 @@ Value *SCEVExpander::visitUMaxExpr(const SCEVUMaxExpr *S) {
|
||||
return LHS;
|
||||
}
|
||||
|
||||
Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty,
|
||||
Instruction *I) {
|
||||
BasicBlock::iterator IP = I;
|
||||
while (isInsertedInstruction(IP) || isa<DbgInfoIntrinsic>(IP))
|
||||
++IP;
|
||||
Builder.SetInsertPoint(IP->getParent(), IP);
|
||||
return expandCodeFor(SH, Ty);
|
||||
}
|
||||
|
||||
Value *SCEVExpander::expandCodeFor(const SCEV *SH, const Type *Ty) {
|
||||
// Expand the code for this SCEV.
|
||||
Value *V = expand(SH);
|
||||
@ -1286,9 +1287,7 @@ Value *SCEVExpander::expand(const SCEV *S) {
|
||||
// there) so that it is guaranteed to dominate any user inside the loop.
|
||||
if (L && S->hasComputableLoopEvolution(L) && L != PostIncLoop)
|
||||
InsertPt = L->getHeader()->getFirstNonPHI();
|
||||
while (isa<DbgInfoIntrinsic>(InsertPt))
|
||||
InsertPt = llvm::next(BasicBlock::iterator(InsertPt));
|
||||
while (isInsertedInstruction(InsertPt))
|
||||
while (isInsertedInstruction(InsertPt) || isa<DbgInfoIntrinsic>(InsertPt))
|
||||
InsertPt = llvm::next(BasicBlock::iterator(InsertPt));
|
||||
break;
|
||||
}
|
||||
@ -1324,7 +1323,8 @@ void SCEVExpander::rememberInstruction(Value *I) {
|
||||
// subsequently inserted code will be dominated.
|
||||
if (Builder.GetInsertPoint() == I) {
|
||||
BasicBlock::iterator It = cast<Instruction>(I);
|
||||
do { ++It; } while (isInsertedInstruction(It));
|
||||
do { ++It; } while (isInsertedInstruction(It) ||
|
||||
isa<DbgInfoIntrinsic>(It));
|
||||
Builder.SetInsertPoint(Builder.GetInsertBlock(), It);
|
||||
}
|
||||
}
|
||||
@ -1332,7 +1332,7 @@ void SCEVExpander::rememberInstruction(Value *I) {
|
||||
void SCEVExpander::restoreInsertPoint(BasicBlock *BB, BasicBlock::iterator I) {
|
||||
// If we acquired more instructions since the old insert point was saved,
|
||||
// advance past them.
|
||||
while (isInsertedInstruction(I)) ++I;
|
||||
while (isInsertedInstruction(I) || isa<DbgInfoIntrinsic>(I)) ++I;
|
||||
|
||||
Builder.SetInsertPoint(BB, I);
|
||||
}
|
||||
|
@ -293,6 +293,8 @@ void BitcodeReaderValueList::ResolveConstantForwardRefs() {
|
||||
} else if (ConstantStruct *UserCS = dyn_cast<ConstantStruct>(UserC)) {
|
||||
NewC = ConstantStruct::get(Context, &NewOps[0], NewOps.size(),
|
||||
UserCS->getType()->isPacked());
|
||||
} else if (ConstantUnion *UserCU = dyn_cast<ConstantUnion>(UserC)) {
|
||||
NewC = ConstantUnion::get(UserCU->getType(), NewOps[0]);
|
||||
} else if (isa<ConstantVector>(UserC)) {
|
||||
NewC = ConstantVector::get(&NewOps[0], NewOps.size());
|
||||
} else {
|
||||
@ -1015,6 +1017,11 @@ bool BitcodeReader::ParseConstants() {
|
||||
Elts.push_back(ValueList.getConstantFwdRef(Record[i],
|
||||
STy->getElementType(i)));
|
||||
V = ConstantStruct::get(STy, Elts);
|
||||
} else if (const UnionType *UnTy = dyn_cast<UnionType>(CurTy)) {
|
||||
uint64_t Index = Record[0];
|
||||
Constant *Val = ValueList.getConstantFwdRef(Record[1],
|
||||
UnTy->getElementType(Index));
|
||||
V = ConstantUnion::get(UnTy, Val);
|
||||
} else if (const ArrayType *ATy = dyn_cast<ArrayType>(CurTy)) {
|
||||
const Type *EltTy = ATy->getElementType();
|
||||
for (unsigned i = 0; i != Size; ++i)
|
||||
|
@ -808,11 +808,25 @@ static void WriteConstants(unsigned FirstVal, unsigned LastVal,
|
||||
else if (isCStr7)
|
||||
AbbrevToUse = CString7Abbrev;
|
||||
} else if (isa<ConstantArray>(C) || isa<ConstantStruct>(V) ||
|
||||
isa<ConstantUnion>(C) || isa<ConstantVector>(V)) {
|
||||
isa<ConstantVector>(V)) {
|
||||
Code = bitc::CST_CODE_AGGREGATE;
|
||||
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
|
||||
Record.push_back(VE.getValueID(C->getOperand(i)));
|
||||
AbbrevToUse = AggregateAbbrev;
|
||||
} else if (isa<ConstantUnion>(C)) {
|
||||
Code = bitc::CST_CODE_AGGREGATE;
|
||||
|
||||
// Unions only have one entry but we must send type along with it.
|
||||
const Type *EntryKind = C->getOperand(0)->getType();
|
||||
|
||||
const UnionType *UnTy = cast<UnionType>(C->getType());
|
||||
int UnionIndex = UnTy->getElementTypeIndex(EntryKind);
|
||||
assert(UnionIndex != -1 && "Constant union contains invalid entry");
|
||||
|
||||
Record.push_back(UnionIndex);
|
||||
Record.push_back(VE.getValueID(C->getOperand(0)));
|
||||
|
||||
AbbrevToUse = AggregateAbbrev;
|
||||
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
||||
switch (CE->getOpcode()) {
|
||||
default:
|
||||
|
@ -1138,6 +1138,21 @@ static void EmitGlobalConstantStruct(const ConstantStruct *CS,
|
||||
"Layout of constant struct may be incorrect!");
|
||||
}
|
||||
|
||||
static void EmitGlobalConstantUnion(const ConstantUnion *CU,
|
||||
unsigned AddrSpace, AsmPrinter &AP) {
|
||||
const TargetData *TD = AP.TM.getTargetData();
|
||||
unsigned Size = TD->getTypeAllocSize(CU->getType());
|
||||
|
||||
const Constant *Contents = CU->getOperand(0);
|
||||
unsigned FilledSize = TD->getTypeAllocSize(Contents->getType());
|
||||
|
||||
// Print the actually filled part
|
||||
AP.EmitGlobalConstant(Contents, AddrSpace);
|
||||
|
||||
// And pad with enough zeroes
|
||||
AP.OutStreamer.EmitZeros(Size-FilledSize, AddrSpace);
|
||||
}
|
||||
|
||||
static void EmitGlobalConstantFP(const ConstantFP *CFP, unsigned AddrSpace,
|
||||
AsmPrinter &AP) {
|
||||
// FP Constants are printed as integer constants to avoid losing
|
||||
@ -1257,9 +1272,6 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {
|
||||
|
||||
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV))
|
||||
return EmitGlobalConstantFP(CFP, AddrSpace, *this);
|
||||
|
||||
if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
|
||||
return EmitGlobalConstantVector(V, AddrSpace, *this);
|
||||
|
||||
if (isa<ConstantPointerNull>(CV)) {
|
||||
unsigned Size = TM.getTargetData()->getTypeAllocSize(CV->getType());
|
||||
@ -1267,6 +1279,12 @@ void AsmPrinter::EmitGlobalConstant(const Constant *CV, unsigned AddrSpace) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (const ConstantUnion *CVU = dyn_cast<ConstantUnion>(CV))
|
||||
return EmitGlobalConstantUnion(CVU, AddrSpace, *this);
|
||||
|
||||
if (const ConstantVector *V = dyn_cast<ConstantVector>(CV))
|
||||
return EmitGlobalConstantVector(V, AddrSpace, *this);
|
||||
|
||||
// Otherwise, it must be a ConstantExpr. Lower it to an MCExpr, then emit it
|
||||
// thread the streamer with EmitValue.
|
||||
OutStreamer.EmitValue(LowerConstant(CV, *this),
|
||||
|
@ -2531,8 +2531,8 @@ void DwarfDebug::emitDebugInfo() {
|
||||
Asm->OutStreamer.AddComment("DWARF version number");
|
||||
Asm->EmitInt16(dwarf::DWARF_VERSION);
|
||||
Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
|
||||
EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"),
|
||||
true, false);
|
||||
EmitSectionOffset(getTempLabel("abbrev_begin"),getTempLabel("section_abbrev"),
|
||||
true);
|
||||
Asm->OutStreamer.AddComment("Address Size (in bytes)");
|
||||
Asm->EmitInt8(TD->getPointerSize());
|
||||
|
||||
@ -2842,8 +2842,8 @@ emitFunctionDebugFrame(const FunctionDebugFrameInfo &DebugFrameInfo) {
|
||||
Asm->OutStreamer.EmitLabel(DebugFrameBegin);
|
||||
|
||||
Asm->OutStreamer.AddComment("FDE CIE offset");
|
||||
EmitSectionOffset(getTempLabel("debug_frame_common"),
|
||||
getTempLabel("section_debug_frame"), true, false);
|
||||
EmitSectionOffset(getTempLabel("debug_frame_common"),
|
||||
getTempLabel("section_debug_frame"), true);
|
||||
|
||||
Asm->OutStreamer.AddComment("FDE initial location");
|
||||
MCSymbol *FuncBeginSym = getDWLabel("func_begin", DebugFrameInfo.Number);
|
||||
@ -2878,8 +2878,7 @@ void DwarfDebug::emitDebugPubNames() {
|
||||
|
||||
Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
|
||||
EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
|
||||
getTempLabel("section_info"),
|
||||
true, false);
|
||||
getTempLabel("section_info"), true);
|
||||
|
||||
Asm->OutStreamer.AddComment("Compilation Unit Length");
|
||||
EmitDifference(getDWLabel("info_end", ModuleCU->getID()),
|
||||
@ -2920,7 +2919,7 @@ void DwarfDebug::emitDebugPubTypes() {
|
||||
|
||||
Asm->OutStreamer.AddComment("Offset of Compilation ModuleCU Info");
|
||||
EmitSectionOffset(getDWLabel("info_begin", ModuleCU->getID()),
|
||||
getTempLabel("section_info"), true, false);
|
||||
getTempLabel("section_info"), true);
|
||||
|
||||
Asm->OutStreamer.AddComment("Compilation ModuleCU Length");
|
||||
EmitDifference(getDWLabel("info_end", ModuleCU->getID()),
|
||||
@ -3068,8 +3067,8 @@ void DwarfDebug::emitDebugInlineInfo() {
|
||||
getTempLabel("section_str"), true);
|
||||
|
||||
Asm->OutStreamer.AddComment("Function name");
|
||||
EmitSectionOffset(getStringPoolEntry(Name), getTempLabel("section_str"),
|
||||
false, true);
|
||||
EmitSectionOffset(getStringPoolEntry(Name), getTempLabel("section_str"),
|
||||
true);
|
||||
EmitULEB128(Labels.size(), "Inline count");
|
||||
|
||||
for (SmallVector<InlineInfoLabels, 4>::iterator LI = Labels.begin(),
|
||||
|
@ -192,7 +192,7 @@ bool BranchFolder::OptimizeFunction(MachineFunction &MF,
|
||||
MadeChange |= MadeChangeThisIteration;
|
||||
}
|
||||
|
||||
// See if any jump tables have become mergable or dead as the code generator
|
||||
// See if any jump tables have become dead as the code generator
|
||||
// did its thing.
|
||||
MachineJumpTableInfo *JTI = MF.getJumpTableInfo();
|
||||
if (JTI == 0) {
|
||||
@ -200,27 +200,8 @@ bool BranchFolder::OptimizeFunction(MachineFunction &MF,
|
||||
return MadeChange;
|
||||
}
|
||||
|
||||
const std::vector<MachineJumpTableEntry> &JTs = JTI->getJumpTables();
|
||||
// Figure out how these jump tables should be merged.
|
||||
std::vector<unsigned> JTMapping;
|
||||
JTMapping.reserve(JTs.size());
|
||||
|
||||
// We always keep the 0th jump table.
|
||||
JTMapping.push_back(0);
|
||||
|
||||
// Scan the jump tables, seeing if there are any duplicates. Note that this
|
||||
// is N^2, which should be fixed someday.
|
||||
for (unsigned i = 1, e = JTs.size(); i != e; ++i) {
|
||||
if (JTs[i].MBBs.empty())
|
||||
JTMapping.push_back(i);
|
||||
else
|
||||
JTMapping.push_back(JTI->getJumpTableIndex(JTs[i].MBBs));
|
||||
}
|
||||
|
||||
// If a jump table was merge with another one, walk the function rewriting
|
||||
// references to jump tables to reference the new JT ID's. Keep track of
|
||||
// whether we see a jump table idx, if not, we can delete the JT.
|
||||
BitVector JTIsLive(JTs.size());
|
||||
// Walk the function to find jump tables that are live.
|
||||
BitVector JTIsLive(JTI->getJumpTables().size());
|
||||
for (MachineFunction::iterator BB = MF.begin(), E = MF.end();
|
||||
BB != E; ++BB) {
|
||||
for (MachineBasicBlock::iterator I = BB->begin(), E = BB->end();
|
||||
@ -228,17 +209,14 @@ bool BranchFolder::OptimizeFunction(MachineFunction &MF,
|
||||
for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) {
|
||||
MachineOperand &Op = I->getOperand(op);
|
||||
if (!Op.isJTI()) continue;
|
||||
unsigned NewIdx = JTMapping[Op.getIndex()];
|
||||
Op.setIndex(NewIdx);
|
||||
|
||||
// Remember that this JT is live.
|
||||
JTIsLive.set(NewIdx);
|
||||
JTIsLive.set(Op.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, remove dead jump tables. This happens either because the
|
||||
// indirect jump was unreachable (and thus deleted) or because the jump
|
||||
// table was merged with some other one.
|
||||
// Finally, remove dead jump tables. This happens when the
|
||||
// indirect jump was unreachable (and thus deleted).
|
||||
for (unsigned i = 0, e = JTIsLive.size(); i != e; ++i)
|
||||
if (!JTIsLive.test(i)) {
|
||||
JTI->RemoveJumpTable(i);
|
||||
@ -1143,22 +1121,6 @@ bool BranchFolder::OptimizeBlock(MachineBasicBlock *MBB) {
|
||||
!IsBetterFallthrough(PriorTBB, MBB))
|
||||
DoTransform = false;
|
||||
|
||||
// We don't want to do this transformation if we have control flow like:
|
||||
// br cond BB2
|
||||
// BB1:
|
||||
// ..
|
||||
// jmp BBX
|
||||
// BB2:
|
||||
// ..
|
||||
// ret
|
||||
//
|
||||
// In this case, we could actually be moving the return block *into* a
|
||||
// loop!
|
||||
if (DoTransform && !MBB->succ_empty() &&
|
||||
(!PriorTBB->canFallThrough() || PriorTBB->empty()))
|
||||
DoTransform = false;
|
||||
|
||||
|
||||
if (DoTransform) {
|
||||
// Reverse the branch so we will fall through on the previous true cond.
|
||||
SmallVector<MachineOperand, 4> NewPriorCond(PriorCond);
|
||||
|
@ -332,7 +332,7 @@ void MachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
MCSymbol *MachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MI,
|
||||
DebugLoc DL) const {
|
||||
MCSymbol *Label = MBB.getParent()->getContext().GetOrCreateTemporarySymbol();
|
||||
MCSymbol *Label = MBB.getParent()->getContext().CreateTempSymbol();
|
||||
BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
|
||||
return Label;
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ void LiveIntervals::printInstrs(raw_ostream &OS) const {
|
||||
for (MachineBasicBlock::iterator mii = mbbi->begin(),
|
||||
mie = mbbi->end(); mii != mie; ++mii) {
|
||||
if (mii->isDebugValue())
|
||||
OS << SlotIndex::getEmptyKey() << '\t' << *mii;
|
||||
OS << " \t" << *mii;
|
||||
else
|
||||
OS << getInstructionIndex(mii) << '\t' << *mii;
|
||||
}
|
||||
@ -583,6 +583,16 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
|
||||
// Look for kills, if it reaches a def before it's killed, then it shouldn't
|
||||
// be considered a livein.
|
||||
MachineBasicBlock::iterator mi = MBB->begin();
|
||||
MachineBasicBlock::iterator E = MBB->end();
|
||||
// Skip over DBG_VALUE at the start of the MBB.
|
||||
if (mi != E && mi->isDebugValue()) {
|
||||
while (++mi != E && mi->isDebugValue())
|
||||
;
|
||||
if (mi == E)
|
||||
// MBB is empty except for DBG_VALUE's.
|
||||
return;
|
||||
}
|
||||
|
||||
SlotIndex baseIndex = MIIdx;
|
||||
SlotIndex start = baseIndex;
|
||||
if (getInstructionFromIndex(baseIndex) == 0)
|
||||
@ -591,12 +601,7 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
|
||||
SlotIndex end = baseIndex;
|
||||
bool SeenDefUse = false;
|
||||
|
||||
MachineBasicBlock::iterator E = MBB->end();
|
||||
while (mi != E) {
|
||||
while (mi != E && mi->isDebugValue())
|
||||
++mi;
|
||||
if (mi == E)
|
||||
break;
|
||||
if (mi->killsRegister(interval.reg, tri_)) {
|
||||
DEBUG(dbgs() << " killed");
|
||||
end = baseIndex.getDefIndex();
|
||||
@ -613,10 +618,11 @@ void LiveIntervals::handleLiveInRegister(MachineBasicBlock *MBB,
|
||||
break;
|
||||
}
|
||||
|
||||
++mi;
|
||||
if (mi != E && !mi->isDebugValue()) {
|
||||
while (++mi != E && mi->isDebugValue())
|
||||
// Skip over DBG_VALUE.
|
||||
;
|
||||
if (mi != E)
|
||||
baseIndex = indexes_->getNextNonNullIndex(baseIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Live-in register might not be used at all.
|
||||
|
@ -88,18 +88,15 @@ MachineFunction::MachineFunction(Function *F, const TargetMachine &TM,
|
||||
unsigned FunctionNum, MCContext &ctx)
|
||||
: Fn(F), Target(TM), Ctx(ctx) {
|
||||
if (TM.getRegisterInfo())
|
||||
RegInfo = new (Allocator.Allocate<MachineRegisterInfo>())
|
||||
MachineRegisterInfo(*TM.getRegisterInfo());
|
||||
RegInfo = new (Allocator) MachineRegisterInfo(*TM.getRegisterInfo());
|
||||
else
|
||||
RegInfo = 0;
|
||||
MFInfo = 0;
|
||||
FrameInfo = new (Allocator.Allocate<MachineFrameInfo>())
|
||||
MachineFrameInfo(*TM.getFrameInfo());
|
||||
FrameInfo = new (Allocator) MachineFrameInfo(*TM.getFrameInfo());
|
||||
if (Fn->hasFnAttr(Attribute::StackAlignment))
|
||||
FrameInfo->setMaxAlignment(Attribute::getStackAlignmentFromAttrs(
|
||||
Fn->getAttributes().getFnAttributes()));
|
||||
ConstantPool = new (Allocator.Allocate<MachineConstantPool>())
|
||||
MachineConstantPool(TM.getTargetData());
|
||||
ConstantPool = new (Allocator) MachineConstantPool(TM.getTargetData());
|
||||
Alignment = TM.getTargetLowering()->getFunctionAlignment(F);
|
||||
FunctionNumber = FunctionNum;
|
||||
JumpTableInfo = 0;
|
||||
@ -132,7 +129,7 @@ MachineJumpTableInfo *MachineFunction::
|
||||
getOrCreateJumpTableInfo(unsigned EntryKind) {
|
||||
if (JumpTableInfo) return JumpTableInfo;
|
||||
|
||||
JumpTableInfo = new (Allocator.Allocate<MachineJumpTableInfo>())
|
||||
JumpTableInfo = new (Allocator)
|
||||
MachineJumpTableInfo((MachineJumpTableInfo::JTEntryKind)EntryKind);
|
||||
return JumpTableInfo;
|
||||
}
|
||||
@ -229,14 +226,13 @@ MachineMemOperand *
|
||||
MachineFunction::getMachineMemOperand(const Value *v, unsigned f,
|
||||
int64_t o, uint64_t s,
|
||||
unsigned base_alignment) {
|
||||
return new (Allocator.Allocate<MachineMemOperand>())
|
||||
MachineMemOperand(v, f, o, s, base_alignment);
|
||||
return new (Allocator) MachineMemOperand(v, f, o, s, base_alignment);
|
||||
}
|
||||
|
||||
MachineMemOperand *
|
||||
MachineFunction::getMachineMemOperand(const MachineMemOperand *MMO,
|
||||
int64_t Offset, uint64_t Size) {
|
||||
return new (Allocator.Allocate<MachineMemOperand>())
|
||||
return new (Allocator)
|
||||
MachineMemOperand(MMO->getValue(), MMO->getFlags(),
|
||||
int64_t(uint64_t(MMO->getOffset()) +
|
||||
uint64_t(Offset)),
|
||||
@ -600,17 +596,15 @@ unsigned MachineJumpTableInfo::getEntryAlignment(const TargetData &TD) const {
|
||||
return ~0;
|
||||
}
|
||||
|
||||
/// getJumpTableIndex - Create a new jump table entry in the jump table info
|
||||
/// or return an existing one.
|
||||
/// createJumpTableIndex - Create a new jump table entry in the jump table info.
|
||||
///
|
||||
unsigned MachineJumpTableInfo::getJumpTableIndex(
|
||||
unsigned MachineJumpTableInfo::createJumpTableIndex(
|
||||
const std::vector<MachineBasicBlock*> &DestBBs) {
|
||||
assert(!DestBBs.empty() && "Cannot create an empty jump table!");
|
||||
JumpTables.push_back(MachineJumpTableEntry(DestBBs));
|
||||
return JumpTables.size()-1;
|
||||
}
|
||||
|
||||
|
||||
/// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update
|
||||
/// the jump tables to branch to New instead.
|
||||
bool MachineJumpTableInfo::ReplaceMBBInJumpTables(MachineBasicBlock *Old,
|
||||
|
@ -739,7 +739,7 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) {
|
||||
|
||||
// Physical registers and those that are not live-out of the block are
|
||||
// killed/dead at their last use/def within this block.
|
||||
if (isPhysReg || !usedOutsideBlock || BBEndsInReturn)
|
||||
if (isPhysReg || !usedOutsideBlock || BBEndsInReturn) {
|
||||
if (MO.isUse()) {
|
||||
// Don't mark uses that are tied to defs as kills.
|
||||
if (!MI->isRegTiedToDefOperand(idx))
|
||||
@ -747,6 +747,7 @@ void RALocal::ComputeLocalLiveness(MachineBasicBlock& MBB) {
|
||||
} else {
|
||||
MO.setIsDead(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -851,8 +851,6 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
||||
case ISD::MERGE_VALUES:
|
||||
case ISD::EH_RETURN:
|
||||
case ISD::FRAME_TO_ARGS_OFFSET:
|
||||
case ISD::FP16_TO_FP32:
|
||||
case ISD::FP32_TO_FP16:
|
||||
// These operations lie about being legal: when they claim to be legal,
|
||||
// they should actually be expanded.
|
||||
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));
|
||||
|
@ -2167,7 +2167,7 @@ SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVector<SDValue, 16>& LdChain,
|
||||
} else
|
||||
return LdOp;
|
||||
} else {
|
||||
unsigned NumElts = WidenWidth / LdWidth;
|
||||
unsigned NumElts = WidenWidth / NewVTWidth;
|
||||
EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
|
||||
SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
|
||||
return DAG.getNode(ISD::BIT_CONVERT, dl, WidenVT, VecOp);
|
||||
|
@ -906,8 +906,7 @@ SDValue SelectionDAG::getConstant(const ConstantInt &Val, EVT VT, bool isT) {
|
||||
return SDValue(N, 0);
|
||||
|
||||
if (!N) {
|
||||
N = NodeAllocator.Allocate<ConstantSDNode>();
|
||||
new (N) ConstantSDNode(isT, &Val, EltVT);
|
||||
N = new (NodeAllocator) ConstantSDNode(isT, &Val, EltVT);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
}
|
||||
@ -950,8 +949,7 @@ SDValue SelectionDAG::getConstantFP(const ConstantFP& V, EVT VT, bool isTarget){
|
||||
return SDValue(N, 0);
|
||||
|
||||
if (!N) {
|
||||
N = NodeAllocator.Allocate<ConstantFPSDNode>();
|
||||
new (N) ConstantFPSDNode(isTarget, &V, EltVT);
|
||||
N = new (NodeAllocator) ConstantFPSDNode(isTarget, &V, EltVT);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
}
|
||||
@ -1010,8 +1008,8 @@ SDValue SelectionDAG::getGlobalAddress(const GlobalValue *GV,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<GlobalAddressSDNode>();
|
||||
new (N) GlobalAddressSDNode(Opc, GV, VT, Offset, TargetFlags);
|
||||
SDNode *N = new (NodeAllocator) GlobalAddressSDNode(Opc, GV, VT,
|
||||
Offset, TargetFlags);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1026,8 +1024,7 @@ SDValue SelectionDAG::getFrameIndex(int FI, EVT VT, bool isTarget) {
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<FrameIndexSDNode>();
|
||||
new (N) FrameIndexSDNode(FI, VT, isTarget);
|
||||
SDNode *N = new (NodeAllocator) FrameIndexSDNode(FI, VT, isTarget);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1046,8 +1043,8 @@ SDValue SelectionDAG::getJumpTable(int JTI, EVT VT, bool isTarget,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<JumpTableSDNode>();
|
||||
new (N) JumpTableSDNode(JTI, VT, isTarget, TargetFlags);
|
||||
SDNode *N = new (NodeAllocator) JumpTableSDNode(JTI, VT, isTarget,
|
||||
TargetFlags);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1072,8 +1069,8 @@ SDValue SelectionDAG::getConstantPool(Constant *C, EVT VT,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<ConstantPoolSDNode>();
|
||||
new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags);
|
||||
SDNode *N = new (NodeAllocator) ConstantPoolSDNode(isTarget, C, VT, Offset,
|
||||
Alignment, TargetFlags);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1099,8 +1096,8 @@ SDValue SelectionDAG::getConstantPool(MachineConstantPoolValue *C, EVT VT,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<ConstantPoolSDNode>();
|
||||
new (N) ConstantPoolSDNode(isTarget, C, VT, Offset, Alignment, TargetFlags);
|
||||
SDNode *N = new (NodeAllocator) ConstantPoolSDNode(isTarget, C, VT, Offset,
|
||||
Alignment, TargetFlags);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1114,8 +1111,7 @@ SDValue SelectionDAG::getBasicBlock(MachineBasicBlock *MBB) {
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<BasicBlockSDNode>();
|
||||
new (N) BasicBlockSDNode(MBB);
|
||||
SDNode *N = new (NodeAllocator) BasicBlockSDNode(MBB);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1130,8 +1126,7 @@ SDValue SelectionDAG::getValueType(EVT VT) {
|
||||
ExtendedValueTypeNodes[VT] : ValueTypeNodes[VT.getSimpleVT().SimpleTy];
|
||||
|
||||
if (N) return SDValue(N, 0);
|
||||
N = NodeAllocator.Allocate<VTSDNode>();
|
||||
new (N) VTSDNode(VT);
|
||||
N = new (NodeAllocator) VTSDNode(VT);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
}
|
||||
@ -1139,8 +1134,7 @@ SDValue SelectionDAG::getValueType(EVT VT) {
|
||||
SDValue SelectionDAG::getExternalSymbol(const char *Sym, EVT VT) {
|
||||
SDNode *&N = ExternalSymbols[Sym];
|
||||
if (N) return SDValue(N, 0);
|
||||
N = NodeAllocator.Allocate<ExternalSymbolSDNode>();
|
||||
new (N) ExternalSymbolSDNode(false, Sym, 0, VT);
|
||||
N = new (NodeAllocator) ExternalSymbolSDNode(false, Sym, 0, VT);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
}
|
||||
@ -1151,8 +1145,7 @@ SDValue SelectionDAG::getTargetExternalSymbol(const char *Sym, EVT VT,
|
||||
TargetExternalSymbols[std::pair<std::string,unsigned char>(Sym,
|
||||
TargetFlags)];
|
||||
if (N) return SDValue(N, 0);
|
||||
N = NodeAllocator.Allocate<ExternalSymbolSDNode>();
|
||||
new (N) ExternalSymbolSDNode(true, Sym, TargetFlags, VT);
|
||||
N = new (NodeAllocator) ExternalSymbolSDNode(true, Sym, TargetFlags, VT);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
}
|
||||
@ -1162,8 +1155,7 @@ SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) {
|
||||
CondCodeNodes.resize(Cond+1);
|
||||
|
||||
if (CondCodeNodes[Cond] == 0) {
|
||||
CondCodeSDNode *N = NodeAllocator.Allocate<CondCodeSDNode>();
|
||||
new (N) CondCodeSDNode(Cond);
|
||||
CondCodeSDNode *N = new (NodeAllocator) CondCodeSDNode(Cond);
|
||||
CondCodeNodes[Cond] = N;
|
||||
AllNodes.push_back(N);
|
||||
}
|
||||
@ -1268,8 +1260,8 @@ SDValue SelectionDAG::getVectorShuffle(EVT VT, DebugLoc dl, SDValue N1,
|
||||
int *MaskAlloc = OperandAllocator.Allocate<int>(NElts);
|
||||
memcpy(MaskAlloc, &MaskVec[0], NElts * sizeof(int));
|
||||
|
||||
ShuffleVectorSDNode *N = NodeAllocator.Allocate<ShuffleVectorSDNode>();
|
||||
new (N) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc);
|
||||
ShuffleVectorSDNode *N =
|
||||
new (NodeAllocator) ShuffleVectorSDNode(VT, dl, N1, N2, MaskAlloc);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1292,8 +1284,8 @@ SDValue SelectionDAG::getConvertRndSat(EVT VT, DebugLoc dl,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
CvtRndSatSDNode *N = NodeAllocator.Allocate<CvtRndSatSDNode>();
|
||||
new (N) CvtRndSatSDNode(VT, dl, Ops, 5, Code);
|
||||
CvtRndSatSDNode *N = new (NodeAllocator) CvtRndSatSDNode(VT, dl, Ops, 5,
|
||||
Code);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1307,8 +1299,7 @@ SDValue SelectionDAG::getRegister(unsigned RegNo, EVT VT) {
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<RegisterSDNode>();
|
||||
new (N) RegisterSDNode(RegNo, VT);
|
||||
SDNode *N = new (NodeAllocator) RegisterSDNode(RegNo, VT);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1323,8 +1314,7 @@ SDValue SelectionDAG::getEHLabel(DebugLoc dl, SDValue Root, MCSymbol *Label) {
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<EHLabelSDNode>();
|
||||
new (N) EHLabelSDNode(dl, Root, Label);
|
||||
SDNode *N = new (NodeAllocator) EHLabelSDNode(dl, Root, Label);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1344,8 +1334,7 @@ SDValue SelectionDAG::getBlockAddress(BlockAddress *BA, EVT VT,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<BlockAddressSDNode>();
|
||||
new (N) BlockAddressSDNode(Opc, VT, BA, TargetFlags);
|
||||
SDNode *N = new (NodeAllocator) BlockAddressSDNode(Opc, VT, BA, TargetFlags);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -1363,8 +1352,7 @@ SDValue SelectionDAG::getSrcValue(const Value *V) {
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<SrcValueSDNode>();
|
||||
new (N) SrcValueSDNode(V);
|
||||
SDNode *N = new (NodeAllocator) SrcValueSDNode(V);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -2313,8 +2301,7 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT) {
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<SDNode>();
|
||||
new (N) SDNode(Opcode, DL, getVTList(VT));
|
||||
SDNode *N = new (NodeAllocator) SDNode(Opcode, DL, getVTList(VT));
|
||||
CSEMap.InsertNode(N, IP);
|
||||
|
||||
AllNodes.push_back(N);
|
||||
@ -2542,12 +2529,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
N = NodeAllocator.Allocate<UnarySDNode>();
|
||||
new (N) UnarySDNode(Opcode, DL, VTs, Operand);
|
||||
N = new (NodeAllocator) UnarySDNode(Opcode, DL, VTs, Operand);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
} else {
|
||||
N = NodeAllocator.Allocate<UnarySDNode>();
|
||||
new (N) UnarySDNode(Opcode, DL, VTs, Operand);
|
||||
N = new (NodeAllocator) UnarySDNode(Opcode, DL, VTs, Operand);
|
||||
}
|
||||
|
||||
AllNodes.push_back(N);
|
||||
@ -2975,12 +2960,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
N = NodeAllocator.Allocate<BinarySDNode>();
|
||||
new (N) BinarySDNode(Opcode, DL, VTs, N1, N2);
|
||||
N = new (NodeAllocator) BinarySDNode(Opcode, DL, VTs, N1, N2);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
} else {
|
||||
N = NodeAllocator.Allocate<BinarySDNode>();
|
||||
new (N) BinarySDNode(Opcode, DL, VTs, N1, N2);
|
||||
N = new (NodeAllocator) BinarySDNode(Opcode, DL, VTs, N1, N2);
|
||||
}
|
||||
|
||||
AllNodes.push_back(N);
|
||||
@ -3053,12 +3036,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
N = NodeAllocator.Allocate<TernarySDNode>();
|
||||
new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3);
|
||||
N = new (NodeAllocator) TernarySDNode(Opcode, DL, VTs, N1, N2, N3);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
} else {
|
||||
N = NodeAllocator.Allocate<TernarySDNode>();
|
||||
new (N) TernarySDNode(Opcode, DL, VTs, N1, N2, N3);
|
||||
N = new (NodeAllocator) TernarySDNode(Opcode, DL, VTs, N1, N2, N3);
|
||||
}
|
||||
|
||||
AllNodes.push_back(N);
|
||||
@ -3659,8 +3640,8 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT,
|
||||
cast<AtomicSDNode>(E)->refineAlignment(MMO);
|
||||
return SDValue(E, 0);
|
||||
}
|
||||
SDNode* N = NodeAllocator.Allocate<AtomicSDNode>();
|
||||
new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Cmp, Swp, MMO);
|
||||
SDNode *N = new (NodeAllocator) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain,
|
||||
Ptr, Cmp, Swp, MMO);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -3722,8 +3703,8 @@ SDValue SelectionDAG::getAtomic(unsigned Opcode, DebugLoc dl, EVT MemVT,
|
||||
cast<AtomicSDNode>(E)->refineAlignment(MMO);
|
||||
return SDValue(E, 0);
|
||||
}
|
||||
SDNode* N = NodeAllocator.Allocate<AtomicSDNode>();
|
||||
new (N) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain, Ptr, Val, MMO);
|
||||
SDNode *N = new (NodeAllocator) AtomicSDNode(Opcode, dl, VTs, MemVT, Chain,
|
||||
Ptr, Val, MMO);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -3801,12 +3782,12 @@ SelectionDAG::getMemIntrinsicNode(unsigned Opcode, DebugLoc dl, SDVTList VTList,
|
||||
return SDValue(E, 0);
|
||||
}
|
||||
|
||||
N = NodeAllocator.Allocate<MemIntrinsicSDNode>();
|
||||
new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO);
|
||||
N = new (NodeAllocator) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps,
|
||||
MemVT, MMO);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
} else {
|
||||
N = NodeAllocator.Allocate<MemIntrinsicSDNode>();
|
||||
new (N) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps, MemVT, MMO);
|
||||
N = new (NodeAllocator) MemIntrinsicSDNode(Opcode, dl, VTList, Ops, NumOps,
|
||||
MemVT, MMO);
|
||||
}
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -3879,8 +3860,8 @@ SelectionDAG::getLoad(ISD::MemIndexedMode AM, DebugLoc dl,
|
||||
cast<LoadSDNode>(E)->refineAlignment(MMO);
|
||||
return SDValue(E, 0);
|
||||
}
|
||||
SDNode *N = NodeAllocator.Allocate<LoadSDNode>();
|
||||
new (N) LoadSDNode(Ops, dl, VTs, AM, ExtType, MemVT, MMO);
|
||||
SDNode *N = new (NodeAllocator) LoadSDNode(Ops, dl, VTs, AM, ExtType,
|
||||
MemVT, MMO);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -3961,8 +3942,8 @@ SDValue SelectionDAG::getStore(SDValue Chain, DebugLoc dl, SDValue Val,
|
||||
cast<StoreSDNode>(E)->refineAlignment(MMO);
|
||||
return SDValue(E, 0);
|
||||
}
|
||||
SDNode *N = NodeAllocator.Allocate<StoreSDNode>();
|
||||
new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, false, VT, MMO);
|
||||
SDNode *N = new (NodeAllocator) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED,
|
||||
false, VT, MMO);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -4025,8 +4006,8 @@ SDValue SelectionDAG::getTruncStore(SDValue Chain, DebugLoc dl, SDValue Val,
|
||||
cast<StoreSDNode>(E)->refineAlignment(MMO);
|
||||
return SDValue(E, 0);
|
||||
}
|
||||
SDNode *N = NodeAllocator.Allocate<StoreSDNode>();
|
||||
new (N) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED, true, SVT, MMO);
|
||||
SDNode *N = new (NodeAllocator) StoreSDNode(Ops, dl, VTs, ISD::UNINDEXED,
|
||||
true, SVT, MMO);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -4048,10 +4029,10 @@ SelectionDAG::getIndexedStore(SDValue OrigStore, DebugLoc dl, SDValue Base,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
SDNode *N = NodeAllocator.Allocate<StoreSDNode>();
|
||||
new (N) StoreSDNode(Ops, dl, VTs, AM,
|
||||
ST->isTruncatingStore(), ST->getMemoryVT(),
|
||||
ST->getMemOperand());
|
||||
SDNode *N = new (NodeAllocator) StoreSDNode(Ops, dl, VTs, AM,
|
||||
ST->isTruncatingStore(),
|
||||
ST->getMemoryVT(),
|
||||
ST->getMemOperand());
|
||||
CSEMap.InsertNode(N, IP);
|
||||
AllNodes.push_back(N);
|
||||
return SDValue(N, 0);
|
||||
@ -4122,12 +4103,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, EVT VT,
|
||||
if (SDNode *E = CSEMap.FindNodeOrInsertPos(ID, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
N = NodeAllocator.Allocate<SDNode>();
|
||||
new (N) SDNode(Opcode, DL, VTs, Ops, NumOps);
|
||||
N = new (NodeAllocator) SDNode(Opcode, DL, VTs, Ops, NumOps);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
} else {
|
||||
N = NodeAllocator.Allocate<SDNode>();
|
||||
new (N) SDNode(Opcode, DL, VTs, Ops, NumOps);
|
||||
N = new (NodeAllocator) SDNode(Opcode, DL, VTs, Ops, NumOps);
|
||||
}
|
||||
|
||||
AllNodes.push_back(N);
|
||||
@ -4190,32 +4169,26 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, SDVTList VTList,
|
||||
return SDValue(E, 0);
|
||||
|
||||
if (NumOps == 1) {
|
||||
N = NodeAllocator.Allocate<UnarySDNode>();
|
||||
new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]);
|
||||
N = new (NodeAllocator) UnarySDNode(Opcode, DL, VTList, Ops[0]);
|
||||
} else if (NumOps == 2) {
|
||||
N = NodeAllocator.Allocate<BinarySDNode>();
|
||||
new (N) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]);
|
||||
N = new (NodeAllocator) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]);
|
||||
} else if (NumOps == 3) {
|
||||
N = NodeAllocator.Allocate<TernarySDNode>();
|
||||
new (N) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1], Ops[2]);
|
||||
N = new (NodeAllocator) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1],
|
||||
Ops[2]);
|
||||
} else {
|
||||
N = NodeAllocator.Allocate<SDNode>();
|
||||
new (N) SDNode(Opcode, DL, VTList, Ops, NumOps);
|
||||
N = new (NodeAllocator) SDNode(Opcode, DL, VTList, Ops, NumOps);
|
||||
}
|
||||
CSEMap.InsertNode(N, IP);
|
||||
} else {
|
||||
if (NumOps == 1) {
|
||||
N = NodeAllocator.Allocate<UnarySDNode>();
|
||||
new (N) UnarySDNode(Opcode, DL, VTList, Ops[0]);
|
||||
N = new (NodeAllocator) UnarySDNode(Opcode, DL, VTList, Ops[0]);
|
||||
} else if (NumOps == 2) {
|
||||
N = NodeAllocator.Allocate<BinarySDNode>();
|
||||
new (N) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]);
|
||||
N = new (NodeAllocator) BinarySDNode(Opcode, DL, VTList, Ops[0], Ops[1]);
|
||||
} else if (NumOps == 3) {
|
||||
N = NodeAllocator.Allocate<TernarySDNode>();
|
||||
new (N) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1], Ops[2]);
|
||||
N = new (NodeAllocator) TernarySDNode(Opcode, DL, VTList, Ops[0], Ops[1],
|
||||
Ops[2]);
|
||||
} else {
|
||||
N = NodeAllocator.Allocate<SDNode>();
|
||||
new (N) SDNode(Opcode, DL, VTList, Ops, NumOps);
|
||||
N = new (NodeAllocator) SDNode(Opcode, DL, VTList, Ops, NumOps);
|
||||
}
|
||||
}
|
||||
AllNodes.push_back(N);
|
||||
@ -4640,7 +4613,7 @@ SDNode *SelectionDAG::MorphNodeTo(SDNode *N, unsigned Opc,
|
||||
// remainder of the current SelectionDAG iteration, so we can allocate
|
||||
// the operands directly out of a pool with no recycling metadata.
|
||||
MN->InitOperands(OperandAllocator.Allocate<SDUse>(NumOps),
|
||||
Ops, NumOps);
|
||||
Ops, NumOps);
|
||||
else
|
||||
MN->InitOperands(MN->LocalOperands, Ops, NumOps);
|
||||
MN->OperandsNeedDelete = false;
|
||||
@ -4814,8 +4787,7 @@ SelectionDAG::getMachineNode(unsigned Opcode, DebugLoc DL, SDVTList VTs,
|
||||
}
|
||||
|
||||
// Allocate a new MachineSDNode.
|
||||
N = NodeAllocator.Allocate<MachineSDNode>();
|
||||
new (N) MachineSDNode(~Opcode, DL, VTs);
|
||||
N = new (NodeAllocator) MachineSDNode(~Opcode, DL, VTs);
|
||||
|
||||
// Initialize the operands list.
|
||||
if (NumOps > array_lengthof(N->LocalOperands))
|
||||
|
@ -1675,11 +1675,10 @@ bool SelectionDAGBuilder::handleJTSwitchCase(CaseRec& CR,
|
||||
}
|
||||
}
|
||||
|
||||
// Create a jump table index for this jump table, or return an existing
|
||||
// one.
|
||||
// Create a jump table index for this jump table.
|
||||
unsigned JTEncoding = TLI.getJumpTableEncoding();
|
||||
unsigned JTI = CurMF->getOrCreateJumpTableInfo(JTEncoding)
|
||||
->getJumpTableIndex(DestBBs);
|
||||
->createJumpTableIndex(DestBBs);
|
||||
|
||||
// Set the jump table information so that we can codegen it as a second
|
||||
// MachineBasicBlock
|
||||
@ -2592,6 +2591,11 @@ void SelectionDAGBuilder::visitGetElementPtr(User &I) {
|
||||
}
|
||||
|
||||
Ty = StTy->getElementType(Field);
|
||||
} else if (const UnionType *UnTy = dyn_cast<UnionType>(Ty)) {
|
||||
unsigned Field = cast<ConstantInt>(Idx)->getZExtValue();
|
||||
|
||||
// Offset canonically 0 for unions, but type changes
|
||||
Ty = UnTy->getElementType(Field);
|
||||
} else {
|
||||
Ty = cast<SequentialType>(Ty)->getElementType();
|
||||
|
||||
@ -4277,6 +4281,9 @@ isInTailCallPosition(CallSite CS, Attributes CalleeRetAttr,
|
||||
--BBI) {
|
||||
if (&*BBI == I)
|
||||
break;
|
||||
// Debug info intrinsics do not get in the way of tail call optimization.
|
||||
if (isa<DbgInfoIntrinsic>(BBI))
|
||||
continue;
|
||||
if (BBI->mayHaveSideEffects() || BBI->mayReadFromMemory() ||
|
||||
!BBI->isSafeToSpeculativelyExecute())
|
||||
return false;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
@ -1639,11 +1640,11 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
|
||||
// Save a copy of the virtual register live interval. We'll manually
|
||||
// merge this into the "real" physical register live interval this is
|
||||
// coalesced with.
|
||||
LiveInterval *SavedLI = 0;
|
||||
OwningPtr<LiveInterval> SavedLI;
|
||||
if (RealDstReg)
|
||||
SavedLI = li_->dupInterval(&SrcInt);
|
||||
SavedLI.reset(li_->dupInterval(&SrcInt));
|
||||
else if (RealSrcReg)
|
||||
SavedLI = li_->dupInterval(&DstInt);
|
||||
SavedLI.reset(li_->dupInterval(&DstInt));
|
||||
|
||||
// Check if it is necessary to propagate "isDead" property.
|
||||
if (!isExtSubReg && !isInsSubReg && !isSubRegToReg) {
|
||||
@ -1853,7 +1854,7 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) {
|
||||
// Manually deleted the live interval copy.
|
||||
if (SavedLI) {
|
||||
SavedLI->clear();
|
||||
delete SavedLI;
|
||||
SavedLI.reset();
|
||||
}
|
||||
|
||||
// If resulting interval has a preference that no longer fits because of subreg
|
||||
|
@ -495,7 +495,7 @@ TailDuplicatePass::TailDuplicate(MachineBasicBlock *TailBB, MachineFunction &MF,
|
||||
if (InstrCount == MaxDuplicateCount) return false;
|
||||
// Remember if we saw a call.
|
||||
if (I->getDesc().isCall()) HasCall = true;
|
||||
if (!I->isPHI())
|
||||
if (!I->isPHI() && !I->isDebugValue())
|
||||
InstrCount += 1;
|
||||
}
|
||||
// Heuristically, don't tail-duplicate calls if it would expand code size,
|
||||
|
@ -12,11 +12,13 @@ add_llvm_library(LLVMMC
|
||||
MCInstPrinter.cpp
|
||||
MCMachOStreamer.cpp
|
||||
MCNullStreamer.cpp
|
||||
MCObjectWriter.cpp
|
||||
MCSection.cpp
|
||||
MCSectionELF.cpp
|
||||
MCSectionMachO.cpp
|
||||
MCStreamer.cpp
|
||||
MCSymbol.cpp
|
||||
MCValue.cpp
|
||||
MachObjectWriter.cpp
|
||||
TargetAsmBackend.cpp
|
||||
)
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "llvm/MC/MCInstPrinter.h"
|
||||
#include "llvm/MC/MCSectionMachO.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
@ -29,7 +30,7 @@ namespace {
|
||||
class MCAsmStreamer : public MCStreamer {
|
||||
formatted_raw_ostream &OS;
|
||||
const MCAsmInfo &MAI;
|
||||
MCInstPrinter *InstPrinter;
|
||||
OwningPtr<MCInstPrinter> InstPrinter;
|
||||
MCCodeEmitter *Emitter;
|
||||
|
||||
SmallString<128> CommentToEmit;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,10 +19,10 @@ MCCodeEmitter::~MCCodeEmitter() {
|
||||
|
||||
const MCFixupKindInfo &MCCodeEmitter::getFixupKindInfo(MCFixupKind Kind) const {
|
||||
static const MCFixupKindInfo Builtins[] = {
|
||||
{ "FK_Data_1", 0, 8 },
|
||||
{ "FK_Data_2", 0, 16 },
|
||||
{ "FK_Data_4", 0, 32 },
|
||||
{ "FK_Data_8", 0, 64 }
|
||||
{ "FK_Data_1", 0, 8, 0 },
|
||||
{ "FK_Data_2", 0, 16, 0 },
|
||||
{ "FK_Data_4", 0, 32, 0 },
|
||||
{ "FK_Data_8", 0, 64, 0 }
|
||||
};
|
||||
|
||||
assert(Kind <= 3 && "Unknown fixup kind");
|
||||
|
@ -49,17 +49,6 @@ MCSymbol *MCContext::CreateTempSymbol() {
|
||||
"tmp" + Twine(NextUniqueID++));
|
||||
}
|
||||
|
||||
|
||||
MCSymbol *MCContext::GetOrCreateTemporarySymbol(StringRef Name) {
|
||||
// If there is no name, create a new anonymous symbol.
|
||||
// FIXME: Remove this. This form of the method should always take a name.
|
||||
if (Name.empty())
|
||||
return GetOrCreateTemporarySymbol(Twine(MAI.getPrivateGlobalPrefix()) +
|
||||
"tmp" + Twine(NextUniqueID++));
|
||||
|
||||
return GetOrCreateSymbol(Name, true);
|
||||
}
|
||||
|
||||
MCSymbol *MCContext::GetOrCreateTemporarySymbol(const Twine &Name) {
|
||||
SmallString<128> NameSV;
|
||||
Name.toVector(NameSV);
|
||||
|
@ -30,7 +30,7 @@ void MCExpr::print(raw_ostream &OS) const {
|
||||
case MCExpr::SymbolRef: {
|
||||
const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(*this);
|
||||
const MCSymbol &Sym = SRE.getSymbol();
|
||||
|
||||
|
||||
// Parenthesize names that start with $ so that they don't look like
|
||||
// absolute names.
|
||||
if (Sym.getName()[0] == '$')
|
||||
@ -59,14 +59,14 @@ void MCExpr::print(raw_ostream &OS) const {
|
||||
|
||||
case MCExpr::Binary: {
|
||||
const MCBinaryExpr &BE = cast<MCBinaryExpr>(*this);
|
||||
|
||||
|
||||
// Only print parens around the LHS if it is non-trivial.
|
||||
if (isa<MCConstantExpr>(BE.getLHS()) || isa<MCSymbolRefExpr>(BE.getLHS())) {
|
||||
OS << *BE.getLHS();
|
||||
} else {
|
||||
OS << '(' << *BE.getLHS() << ')';
|
||||
}
|
||||
|
||||
|
||||
switch (BE.getOpcode()) {
|
||||
default: assert(0 && "Invalid opcode!");
|
||||
case MCBinaryExpr::Add:
|
||||
@ -77,7 +77,7 @@ void MCExpr::print(raw_ostream &OS) const {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
OS << '+';
|
||||
break;
|
||||
case MCBinaryExpr::And: OS << '&'; break;
|
||||
@ -98,7 +98,7 @@ void MCExpr::print(raw_ostream &OS) const {
|
||||
case MCBinaryExpr::Sub: OS << '-'; break;
|
||||
case MCBinaryExpr::Xor: OS << '^'; break;
|
||||
}
|
||||
|
||||
|
||||
// Only print parens around the LHS if it is non-trivial.
|
||||
if (isa<MCConstantExpr>(BE.getRHS()) || isa<MCSymbolRefExpr>(BE.getRHS())) {
|
||||
OS << *BE.getRHS();
|
||||
@ -193,7 +193,7 @@ void MCTargetExpr::Anchor() {}
|
||||
|
||||
bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const {
|
||||
MCValue Value;
|
||||
|
||||
|
||||
if (!EvaluateAsRelocatable(Value, Layout) || !Value.isAbsolute())
|
||||
return false;
|
||||
|
||||
@ -201,16 +201,16 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool EvaluateSymbolicAdd(const MCValue &LHS, const MCSymbol *RHS_A,
|
||||
const MCSymbol *RHS_B, int64_t RHS_Cst,
|
||||
static bool EvaluateSymbolicAdd(const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
|
||||
const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
|
||||
MCValue &Res) {
|
||||
// We can't add or subtract two symbols.
|
||||
if ((LHS.getSymA() && RHS_A) ||
|
||||
(LHS.getSymB() && RHS_B))
|
||||
return false;
|
||||
|
||||
const MCSymbol *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
|
||||
const MCSymbol *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
|
||||
const MCSymbolRefExpr *A = LHS.getSymA() ? LHS.getSymA() : RHS_A;
|
||||
const MCSymbolRefExpr *B = LHS.getSymB() ? LHS.getSymB() : RHS_B;
|
||||
if (B) {
|
||||
// If we have a negated symbol, then we must have also have a non-negated
|
||||
// symbol in order to encode the expression. We can do this check later to
|
||||
@ -228,13 +228,14 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
|
||||
switch (getKind()) {
|
||||
case Target:
|
||||
return cast<MCTargetExpr>(this)->EvaluateAsRelocatableImpl(Res, Layout);
|
||||
|
||||
|
||||
case Constant:
|
||||
Res = MCValue::get(cast<MCConstantExpr>(this)->getValue());
|
||||
return true;
|
||||
|
||||
case SymbolRef: {
|
||||
const MCSymbol &Sym = cast<MCSymbolRefExpr>(this)->getSymbol();
|
||||
const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(this);
|
||||
const MCSymbol &Sym = SRE->getSymbol();
|
||||
|
||||
// Evaluate recursively if this is a variable.
|
||||
if (Sym.isVariable()) {
|
||||
@ -245,9 +246,12 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
|
||||
// layout object and the target requests it.
|
||||
if (Layout && Res.getSymB() &&
|
||||
Layout->getAssembler().getBackend().hasAbsolutizedSet() &&
|
||||
Res.getSymA()->isDefined() && Res.getSymB()->isDefined()) {
|
||||
MCSymbolData &A = Layout->getAssembler().getSymbolData(*Res.getSymA());
|
||||
MCSymbolData &B = Layout->getAssembler().getSymbolData(*Res.getSymB());
|
||||
Res.getSymA()->getSymbol().isDefined() &&
|
||||
Res.getSymB()->getSymbol().isDefined()) {
|
||||
MCSymbolData &A =
|
||||
Layout->getAssembler().getSymbolData(Res.getSymA()->getSymbol());
|
||||
MCSymbolData &B =
|
||||
Layout->getAssembler().getSymbolData(Res.getSymB()->getSymbol());
|
||||
Res = MCValue::get(+ A.getFragment()->getAddress() + A.getOffset()
|
||||
- B.getFragment()->getAddress() - B.getOffset()
|
||||
+ Res.getConstant());
|
||||
@ -256,7 +260,7 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
|
||||
return true;
|
||||
}
|
||||
|
||||
Res = MCValue::get(&Sym, 0, 0);
|
||||
Res = MCValue::get(SRE, 0, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -277,13 +281,13 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
|
||||
/// -(a - b + const) ==> (b - a - const)
|
||||
if (Value.getSymA() && !Value.getSymB())
|
||||
return false;
|
||||
Res = MCValue::get(Value.getSymB(), Value.getSymA(),
|
||||
-Value.getConstant());
|
||||
Res = MCValue::get(Value.getSymB(), Value.getSymA(),
|
||||
-Value.getConstant());
|
||||
break;
|
||||
case MCUnaryExpr::Not:
|
||||
if (!Value.isAbsolute())
|
||||
return false;
|
||||
Res = MCValue::get(~Value.getConstant());
|
||||
Res = MCValue::get(~Value.getConstant());
|
||||
break;
|
||||
case MCUnaryExpr::Plus:
|
||||
Res = Value;
|
||||
@ -296,7 +300,7 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
|
||||
case Binary: {
|
||||
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
|
||||
MCValue LHSValue, RHSValue;
|
||||
|
||||
|
||||
if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) ||
|
||||
!ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout))
|
||||
return false;
|
||||
|
@ -45,7 +45,6 @@ class MCMachOStreamer : public MCStreamer {
|
||||
|
||||
private:
|
||||
MCAssembler Assembler;
|
||||
MCCodeEmitter *Emitter;
|
||||
MCSectionData *CurSectionData;
|
||||
|
||||
private:
|
||||
@ -61,7 +60,7 @@ class MCMachOStreamer : public MCStreamer {
|
||||
public:
|
||||
MCMachOStreamer(MCContext &Context, TargetAsmBackend &TAB,
|
||||
raw_ostream &_OS, MCCodeEmitter *_Emitter)
|
||||
: MCStreamer(Context), Assembler(Context, TAB, _OS), Emitter(_Emitter),
|
||||
: MCStreamer(Context), Assembler(Context, TAB, *_Emitter, _OS),
|
||||
CurSectionData(0) {}
|
||||
~MCMachOStreamer() {}
|
||||
|
||||
@ -370,15 +369,12 @@ void MCMachOStreamer::EmitInstruction(const MCInst &Inst) {
|
||||
if (Inst.getOperand(i).isExpr())
|
||||
AddValueSymbols(Inst.getOperand(i).getExpr());
|
||||
|
||||
if (!Emitter)
|
||||
llvm_unreachable("no code emitter available!");
|
||||
|
||||
CurSectionData->setHasInstructions(true);
|
||||
|
||||
SmallVector<MCFixup, 4> Fixups;
|
||||
SmallString<256> Code;
|
||||
raw_svector_ostream VecOS(Code);
|
||||
Emitter->EncodeInstruction(Inst, VecOS, Fixups);
|
||||
Assembler.getEmitter().EncodeInstruction(Inst, VecOS, Fixups);
|
||||
VecOS.flush();
|
||||
|
||||
// Add the fixups and data.
|
||||
|
15
lib/MC/MCObjectWriter.cpp
Normal file
15
lib/MC/MCObjectWriter.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
//===- lib/MC/MCObjectWriter.cpp - MCObjectWriter implementation ----------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/MC/MCObjectWriter.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
MCObjectWriter::~MCObjectWriter() {
|
||||
}
|
@ -8,6 +8,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/MC/MCValue.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
@ -19,10 +20,12 @@ void MCValue::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
|
||||
return;
|
||||
}
|
||||
|
||||
OS << *getSymA();
|
||||
getSymA()->print(OS);
|
||||
|
||||
if (getSymB())
|
||||
OS << " - " << *getSymB();
|
||||
if (getSymB()) {
|
||||
OS << " - ";
|
||||
getSymB()->print(OS);
|
||||
}
|
||||
|
||||
if (getConstant())
|
||||
OS << " + " << getConstant();
|
||||
|
1109
lib/MC/MachObjectWriter.cpp
Normal file
1109
lib/MC/MachObjectWriter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -11,7 +11,10 @@
|
||||
using namespace llvm;
|
||||
|
||||
TargetAsmBackend::TargetAsmBackend(const Target &T)
|
||||
: TheTarget(T)
|
||||
: TheTarget(T),
|
||||
HasAbsolutizedSet(false),
|
||||
HasReliableSymbolDifference(false),
|
||||
HasScatteredSymbols(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include <cassert>
|
||||
@ -130,6 +131,15 @@ bool FoldingSetNodeID::operator==(const FoldingSetNodeID &RHS)const{
|
||||
return memcmp(&Bits[0], &RHS.Bits[0], Bits.size()*sizeof(Bits[0])) == 0;
|
||||
}
|
||||
|
||||
/// Intern - Copy this node's data to a memory region allocated from the
|
||||
/// given allocator and return a FoldingSetNodeIDRef describing the
|
||||
/// interned data.
|
||||
FoldingSetNodeIDRef
|
||||
FoldingSetNodeID::Intern(BumpPtrAllocator &Allocator) const {
|
||||
unsigned *New = Allocator.Allocate<unsigned>(Bits.size());
|
||||
std::uninitialized_copy(Bits.begin(), Bits.end(), New);
|
||||
return FoldingSetNodeIDRef(New, Bits.size());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// Helper functions for FoldingSetImpl.
|
||||
|
@ -39,8 +39,8 @@ static SmartMutex<true> SignalsMutex;
|
||||
/// InterruptFunction - The function to call if ctrl-c is pressed.
|
||||
static void (*InterruptFunction)() = 0;
|
||||
|
||||
static std::vector<sys::Path> *FilesToRemove = 0;
|
||||
static std::vector<std::pair<void(*)(void*), void*> > *CallBacksToRun = 0;
|
||||
static std::vector<sys::Path> FilesToRemove;
|
||||
static std::vector<std::pair<void(*)(void*), void*> > CallBacksToRun;
|
||||
|
||||
// IntSigs - Signals that may interrupt the program at any time.
|
||||
static const int IntSigs[] = {
|
||||
@ -126,11 +126,10 @@ static RETSIGTYPE SignalHandler(int Sig) {
|
||||
sigprocmask(SIG_UNBLOCK, &SigMask, 0);
|
||||
|
||||
SignalsMutex.acquire();
|
||||
if (FilesToRemove != 0)
|
||||
while (!FilesToRemove->empty()) {
|
||||
FilesToRemove->back().eraseFromDisk(true);
|
||||
FilesToRemove->pop_back();
|
||||
}
|
||||
while (!FilesToRemove.empty()) {
|
||||
FilesToRemove.back().eraseFromDisk(true);
|
||||
FilesToRemove.pop_back();
|
||||
}
|
||||
|
||||
if (std::find(IntSigs, IntSigsEnd, Sig) != IntSigsEnd) {
|
||||
if (InterruptFunction) {
|
||||
@ -149,9 +148,8 @@ static RETSIGTYPE SignalHandler(int Sig) {
|
||||
SignalsMutex.release();
|
||||
|
||||
// Otherwise if it is a fault (like SEGV) run any handler.
|
||||
if (CallBacksToRun)
|
||||
for (unsigned i = 0, e = CallBacksToRun->size(); i != e; ++i)
|
||||
(*CallBacksToRun)[i].first((*CallBacksToRun)[i].second);
|
||||
for (unsigned i = 0, e = CallBacksToRun.size(); i != e; ++i)
|
||||
CallBacksToRun[i].first(CallBacksToRun[i].second);
|
||||
}
|
||||
|
||||
|
||||
@ -167,10 +165,7 @@ void llvm::sys::SetInterruptFunction(void (*IF)()) {
|
||||
bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename,
|
||||
std::string* ErrMsg) {
|
||||
SignalsMutex.acquire();
|
||||
if (FilesToRemove == 0)
|
||||
FilesToRemove = new std::vector<sys::Path>();
|
||||
|
||||
FilesToRemove->push_back(Filename);
|
||||
FilesToRemove.push_back(Filename);
|
||||
|
||||
SignalsMutex.release();
|
||||
|
||||
@ -182,9 +177,7 @@ bool llvm::sys::RemoveFileOnSignal(const sys::Path &Filename,
|
||||
/// to the process. The handler can have a cookie passed to it to identify
|
||||
/// what instance of the handler it is.
|
||||
void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) {
|
||||
if (CallBacksToRun == 0)
|
||||
CallBacksToRun = new std::vector<std::pair<void(*)(void*), void*> >();
|
||||
CallBacksToRun->push_back(std::make_pair(FnPtr, Cookie));
|
||||
CallBacksToRun.push_back(std::make_pair(FnPtr, Cookie));
|
||||
RegisterHandlers();
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,10 @@ namespace ARM_AM {
|
||||
add = '+', sub = '-'
|
||||
};
|
||||
|
||||
static inline const char *getAddrOpcStr(AddrOpc Op) {
|
||||
return Op == sub ? "-" : "";
|
||||
}
|
||||
|
||||
static inline const char *getShiftOpcStr(ShiftOpc Op) {
|
||||
switch (Op) {
|
||||
default: assert(0 && "Unknown shift opc!");
|
||||
@ -78,16 +82,6 @@ namespace ARM_AM {
|
||||
}
|
||||
}
|
||||
|
||||
static inline const char *getAMSubModeAltStr(AMSubMode Mode, bool isLD) {
|
||||
switch (Mode) {
|
||||
default: assert(0 && "Unknown addressing sub-mode!");
|
||||
case ARM_AM::ia: return isLD ? "fd" : "ea";
|
||||
case ARM_AM::ib: return isLD ? "ed" : "fa";
|
||||
case ARM_AM::da: return isLD ? "fa" : "ed";
|
||||
case ARM_AM::db: return isLD ? "ea" : "fd";
|
||||
}
|
||||
}
|
||||
|
||||
/// rotr32 - Rotate a 32-bit unsigned value right by a specified # bits.
|
||||
///
|
||||
static inline unsigned rotr32(unsigned Val, unsigned Amt) {
|
||||
@ -473,20 +467,13 @@ namespace ARM_AM {
|
||||
// IB - Increment before
|
||||
// DA - Decrement after
|
||||
// DB - Decrement before
|
||||
//
|
||||
// If the 4th bit (writeback)is set, then the base register is updated after
|
||||
// the memory transfer.
|
||||
|
||||
static inline AMSubMode getAM4SubMode(unsigned Mode) {
|
||||
return (AMSubMode)(Mode & 0x7);
|
||||
}
|
||||
|
||||
static inline unsigned getAM4ModeImm(AMSubMode SubMode, bool WB = false) {
|
||||
return (int)SubMode | ((int)WB << 3);
|
||||
}
|
||||
|
||||
static inline bool getAM4WBFlag(unsigned Mode) {
|
||||
return (Mode >> 3) & 1;
|
||||
static inline unsigned getAM4ModeImm(AMSubMode SubMode) {
|
||||
return (int)SubMode;
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -501,9 +488,9 @@ namespace ARM_AM {
|
||||
// operation in bit 8 and the immediate in bits 0-7.
|
||||
//
|
||||
// This is also used for FP load/store multiple ops. The second operand
|
||||
// encodes the writeback mode in bit 8 and the number of registers (or 2
|
||||
// times the number of registers for DPR ops) in bits 0-7. In addition,
|
||||
// bits 9-11 encode one of the following two sub-modes:
|
||||
// encodes the number of registers (or 2 times the number of registers
|
||||
// for DPR ops) in bits 0-7. In addition, bits 8-10 encode one of the
|
||||
// following two sub-modes:
|
||||
//
|
||||
// IA - Increment after
|
||||
// DB - Decrement before
|
||||
@ -522,17 +509,13 @@ namespace ARM_AM {
|
||||
|
||||
/// getAM5Opc - This function encodes the addrmode5 opc field for VLDM and
|
||||
/// VSTM instructions.
|
||||
static inline unsigned getAM5Opc(AMSubMode SubMode, bool WB,
|
||||
unsigned char Offset) {
|
||||
static inline unsigned getAM5Opc(AMSubMode SubMode, unsigned char Offset) {
|
||||
assert((SubMode == ia || SubMode == db) &&
|
||||
"Illegal addressing mode 5 sub-mode!");
|
||||
return ((int)SubMode << 9) | ((int)WB << 8) | Offset;
|
||||
return ((int)SubMode << 8) | Offset;
|
||||
}
|
||||
static inline AMSubMode getAM5SubMode(unsigned AM5Opc) {
|
||||
return (AMSubMode)((AM5Opc >> 9) & 0x7);
|
||||
}
|
||||
static inline bool getAM5WBFlag(unsigned AM5Opc) {
|
||||
return ((AM5Opc >> 8) & 1);
|
||||
return (AMSubMode)((AM5Opc >> 8) & 0x7);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -541,23 +524,11 @@ namespace ARM_AM {
|
||||
//
|
||||
// This is used for NEON load / store instructions.
|
||||
//
|
||||
// addrmode6 := reg with optional writeback and alignment
|
||||
// addrmode6 := reg with optional alignment
|
||||
//
|
||||
// This is stored in four operands [regaddr, regupdate, opc, align]. The
|
||||
// first is the address register. The second register holds the value of
|
||||
// a post-access increment for writeback or reg0 if no writeback or if the
|
||||
// writeback increment is the size of the memory access. The third
|
||||
// operand encodes whether there is writeback to the address register. The
|
||||
// fourth operand is the value of the alignment specifier to use or zero if
|
||||
// no explicit alignment.
|
||||
|
||||
static inline unsigned getAM6Opc(bool WB = false) {
|
||||
return (int)WB;
|
||||
}
|
||||
|
||||
static inline bool getAM6WBFlag(unsigned Mode) {
|
||||
return Mode & 1;
|
||||
}
|
||||
// This is stored in two operands [regaddr, align]. The first is the
|
||||
// address register. The second operand is the value of the alignment
|
||||
// specifier to use or zero if no explicit alignment.
|
||||
|
||||
} // end namespace ARM_AM
|
||||
} // end namespace llvm
|
||||
|
@ -650,39 +650,49 @@ ARMBaseInstrInfo::copyRegToReg(MachineBasicBlock &MBB,
|
||||
if (SrcRC == ARM::tGPRRegisterClass)
|
||||
SrcRC = ARM::GPRRegisterClass;
|
||||
|
||||
if (DestRC != SrcRC) {
|
||||
if (DestRC->getSize() != SrcRC->getSize())
|
||||
return false;
|
||||
// Allow DPR / DPR_VFP2 / DPR_8 cross-class copies.
|
||||
if (DestRC == ARM::DPR_8RegisterClass)
|
||||
DestRC = ARM::DPR_VFP2RegisterClass;
|
||||
if (SrcRC == ARM::DPR_8RegisterClass)
|
||||
SrcRC = ARM::DPR_VFP2RegisterClass;
|
||||
|
||||
// Allow DPR / DPR_VFP2 / DPR_8 cross-class copies.
|
||||
// Allow QPR / QPR_VFP2 / QPR_8 cross-class copies.
|
||||
if (DestRC->getSize() != 8 && DestRC->getSize() != 16)
|
||||
return false;
|
||||
}
|
||||
// Allow QPR / QPR_VFP2 / QPR_8 cross-class copies.
|
||||
if (DestRC == ARM::QPR_VFP2RegisterClass ||
|
||||
DestRC == ARM::QPR_8RegisterClass)
|
||||
DestRC = ARM::QPRRegisterClass;
|
||||
if (SrcRC == ARM::QPR_VFP2RegisterClass ||
|
||||
SrcRC == ARM::QPR_8RegisterClass)
|
||||
SrcRC = ARM::QPRRegisterClass;
|
||||
|
||||
// Disallow copies of unequal sizes.
|
||||
if (DestRC != SrcRC && DestRC->getSize() != SrcRC->getSize())
|
||||
return false;
|
||||
|
||||
if (DestRC == ARM::GPRRegisterClass) {
|
||||
AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr),
|
||||
DestReg).addReg(SrcReg)));
|
||||
} else if (DestRC == ARM::SPRRegisterClass) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVS), DestReg)
|
||||
.addReg(SrcReg));
|
||||
} else if (DestRC == ARM::DPRRegisterClass) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVD), DestReg)
|
||||
.addReg(SrcReg));
|
||||
} else if (DestRC == ARM::DPR_VFP2RegisterClass ||
|
||||
DestRC == ARM::DPR_8RegisterClass ||
|
||||
SrcRC == ARM::DPR_VFP2RegisterClass ||
|
||||
SrcRC == ARM::DPR_8RegisterClass) {
|
||||
// Always use neon reg-reg move if source or dest is NEON-only regclass.
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVDneon),
|
||||
DestReg).addReg(SrcReg));
|
||||
} else if (DestRC == ARM::QPRRegisterClass ||
|
||||
DestRC == ARM::QPR_VFP2RegisterClass ||
|
||||
DestRC == ARM::QPR_8RegisterClass) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVQ),
|
||||
DestReg).addReg(SrcReg));
|
||||
if (SrcRC == ARM::SPRRegisterClass)
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VMOVRS), DestReg)
|
||||
.addReg(SrcReg));
|
||||
else
|
||||
AddDefaultCC(AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::MOVr),
|
||||
DestReg).addReg(SrcReg)));
|
||||
} else {
|
||||
return false;
|
||||
unsigned Opc;
|
||||
|
||||
if (DestRC == ARM::SPRRegisterClass)
|
||||
Opc = (SrcRC == ARM::GPRRegisterClass ? ARM::VMOVSR : ARM::VMOVS);
|
||||
else if (DestRC == ARM::DPRRegisterClass)
|
||||
Opc = ARM::VMOVD;
|
||||
else if (DestRC == ARM::DPR_VFP2RegisterClass ||
|
||||
SrcRC == ARM::DPR_VFP2RegisterClass)
|
||||
// Always use neon reg-reg move if source or dest is NEON-only regclass.
|
||||
Opc = ARM::VMOVDneon;
|
||||
else if (DestRC == ARM::QPRRegisterClass)
|
||||
Opc = ARM::VMOVQ;
|
||||
else
|
||||
return false;
|
||||
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(Opc), DestReg)
|
||||
.addReg(SrcReg));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -727,10 +737,9 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
assert((RC == ARM::QPRRegisterClass ||
|
||||
RC == ARM::QPR_VFP2RegisterClass) && "Unknown regclass!");
|
||||
// FIXME: Neon instructions should support predicates
|
||||
if (Align >= 16
|
||||
&& (getRegisterInfo().canRealignStack(MF))) {
|
||||
if (Align >= 16 && (getRegisterInfo().canRealignStack(MF))) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VST1q64))
|
||||
.addFrameIndex(FI).addImm(0).addImm(0).addImm(128)
|
||||
.addFrameIndex(FI).addImm(128)
|
||||
.addMemOperand(MMO)
|
||||
.addReg(SrcReg, getKillRegState(isKill)));
|
||||
} else {
|
||||
@ -780,7 +789,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
|
||||
if (Align >= 16
|
||||
&& (getRegisterInfo().canRealignStack(MF))) {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLD1q64), DestReg)
|
||||
.addFrameIndex(FI).addImm(0).addImm(0).addImm(128)
|
||||
.addFrameIndex(FI).addImm(128)
|
||||
.addMemOperand(MMO));
|
||||
} else {
|
||||
AddDefaultPred(BuildMI(MBB, I, DL, get(ARM::VLDRQ), DestReg)
|
||||
|
@ -93,34 +93,34 @@ namespace ARMII {
|
||||
StMiscFrm = 9 << FormShift,
|
||||
LdStMulFrm = 10 << FormShift,
|
||||
|
||||
LdStExFrm = 28 << FormShift,
|
||||
LdStExFrm = 11 << FormShift,
|
||||
|
||||
// Miscellaneous arithmetic instructions
|
||||
ArithMiscFrm = 11 << FormShift,
|
||||
ArithMiscFrm = 12 << FormShift,
|
||||
|
||||
// Extend instructions
|
||||
ExtFrm = 12 << FormShift,
|
||||
ExtFrm = 13 << FormShift,
|
||||
|
||||
// VFP formats
|
||||
VFPUnaryFrm = 13 << FormShift,
|
||||
VFPBinaryFrm = 14 << FormShift,
|
||||
VFPConv1Frm = 15 << FormShift,
|
||||
VFPConv2Frm = 16 << FormShift,
|
||||
VFPConv3Frm = 17 << FormShift,
|
||||
VFPConv4Frm = 18 << FormShift,
|
||||
VFPConv5Frm = 19 << FormShift,
|
||||
VFPLdStFrm = 20 << FormShift,
|
||||
VFPLdStMulFrm = 21 << FormShift,
|
||||
VFPMiscFrm = 22 << FormShift,
|
||||
VFPUnaryFrm = 14 << FormShift,
|
||||
VFPBinaryFrm = 15 << FormShift,
|
||||
VFPConv1Frm = 16 << FormShift,
|
||||
VFPConv2Frm = 17 << FormShift,
|
||||
VFPConv3Frm = 18 << FormShift,
|
||||
VFPConv4Frm = 19 << FormShift,
|
||||
VFPConv5Frm = 20 << FormShift,
|
||||
VFPLdStFrm = 21 << FormShift,
|
||||
VFPLdStMulFrm = 22 << FormShift,
|
||||
VFPMiscFrm = 23 << FormShift,
|
||||
|
||||
// Thumb format
|
||||
ThumbFrm = 23 << FormShift,
|
||||
ThumbFrm = 24 << FormShift,
|
||||
|
||||
// NEON format
|
||||
NEONFrm = 24 << FormShift,
|
||||
NEONGetLnFrm = 25 << FormShift,
|
||||
NEONSetLnFrm = 26 << FormShift,
|
||||
NEONDupFrm = 27 << FormShift,
|
||||
NEONFrm = 25 << FormShift,
|
||||
NEONGetLnFrm = 26 << FormShift,
|
||||
NEONSetLnFrm = 27 << FormShift,
|
||||
NEONDupFrm = 28 << FormShift,
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Misc flags.
|
||||
|
@ -80,7 +80,7 @@ unsigned ARMBaseRegisterInfo::getRegisterNumbering(unsigned RegEnum,
|
||||
case D23: return 23;
|
||||
case D24: return 24;
|
||||
case D25: return 25;
|
||||
case D26: return 27;
|
||||
case D26: return 26;
|
||||
case D27: return 27;
|
||||
case D28: return 28;
|
||||
case D29: return 29;
|
||||
|
@ -55,12 +55,12 @@ namespace {
|
||||
const std::vector<MachineConstantPoolEntry> *MCPEs;
|
||||
const std::vector<MachineJumpTableEntry> *MJTEs;
|
||||
bool IsPIC;
|
||||
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<MachineModuleInfo>();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
|
||||
|
||||
static char ID;
|
||||
public:
|
||||
ARMCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce)
|
||||
@ -68,7 +68,7 @@ namespace {
|
||||
TD(tm.getTargetData()), TM(tm),
|
||||
MCE(mce), MCPEs(0), MJTEs(0),
|
||||
IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
|
||||
|
||||
|
||||
/// getBinaryCodeForInstr - This function, generated by the
|
||||
/// CodeEmitterGenerator using TableGen, produces the binary encoding for
|
||||
/// machine instructions.
|
||||
@ -163,7 +163,7 @@ namespace {
|
||||
|
||||
char ARMCodeEmitter::ID = 0;
|
||||
|
||||
/// createARMJITCodeEmitterPass - Return a pass that emits the collected ARM
|
||||
/// createARMJITCodeEmitterPass - Return a pass that emits the collected ARM
|
||||
/// code to the specified MCE object.
|
||||
FunctionPass *llvm::createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
JITCodeEmitter &JCE) {
|
||||
@ -617,8 +617,7 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
|
||||
}
|
||||
}
|
||||
|
||||
unsigned ARMCodeEmitter::getMachineSoRegOpValue(
|
||||
const MachineInstr &MI,
|
||||
unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI,
|
||||
const TargetInstrDesc &TID,
|
||||
const MachineOperand &MO,
|
||||
unsigned OpIdx) {
|
||||
@ -690,7 +689,7 @@ unsigned ARMCodeEmitter::getMachineSoImmOpValue(unsigned SoImm) {
|
||||
}
|
||||
|
||||
unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI,
|
||||
const TargetInstrDesc &TID) const {
|
||||
const TargetInstrDesc &TID) const {
|
||||
for (unsigned i = MI.getNumOperands(), e = TID.getNumOperands(); i != e; --i){
|
||||
const MachineOperand &MO = MI.getOperand(i-1);
|
||||
if (MO.isReg() && MO.isDef() && MO.getReg() == ARM::CPSR)
|
||||
@ -699,8 +698,7 @@ unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ARMCodeEmitter::emitDataProcessingInstruction(
|
||||
const MachineInstr &MI,
|
||||
void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI,
|
||||
unsigned ImplicitRd,
|
||||
unsigned ImplicitRn) {
|
||||
const TargetInstrDesc &TID = MI.getDesc();
|
||||
@ -765,8 +763,7 @@ void ARMCodeEmitter::emitDataProcessingInstruction(
|
||||
emitWordLE(Binary);
|
||||
}
|
||||
|
||||
void ARMCodeEmitter::emitLoadStoreInstruction(
|
||||
const MachineInstr &MI,
|
||||
void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI,
|
||||
unsigned ImplicitRd,
|
||||
unsigned ImplicitRn) {
|
||||
const TargetInstrDesc &TID = MI.getDesc();
|
||||
@ -841,7 +838,7 @@ void ARMCodeEmitter::emitLoadStoreInstruction(
|
||||
}
|
||||
|
||||
void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI,
|
||||
unsigned ImplicitRn) {
|
||||
unsigned ImplicitRn) {
|
||||
const TargetInstrDesc &TID = MI.getDesc();
|
||||
unsigned Form = TID.TSFlags & ARMII::FormMask;
|
||||
bool IsPrePost = (TID.TSFlags & ARMII::IndexModeMask) != 0;
|
||||
@ -950,7 +947,7 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
|
||||
Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(MO.getImm()));
|
||||
|
||||
// Set bit W(21)
|
||||
if (ARM_AM::getAM4WBFlag(MO.getImm()))
|
||||
if (IsUpdating)
|
||||
Binary |= 0x1 << ARMII::W_BitShift;
|
||||
|
||||
// Set registers
|
||||
@ -1238,8 +1235,7 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) {
|
||||
emitWordLE(Binary);
|
||||
}
|
||||
|
||||
void ARMCodeEmitter::emitVFPConversionInstruction(
|
||||
const MachineInstr &MI) {
|
||||
void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
|
||||
const TargetInstrDesc &TID = MI.getDesc();
|
||||
unsigned Form = TID.TSFlags & ARMII::FormMask;
|
||||
|
||||
@ -1329,8 +1325,8 @@ void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) {
|
||||
emitWordLE(Binary);
|
||||
}
|
||||
|
||||
void ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(
|
||||
const MachineInstr &MI) {
|
||||
void
|
||||
ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(const MachineInstr &MI) {
|
||||
const TargetInstrDesc &TID = MI.getDesc();
|
||||
bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0;
|
||||
|
||||
@ -1353,7 +1349,7 @@ void ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(
|
||||
Binary |= getAddrModeUPBits(ARM_AM::getAM5SubMode(MO.getImm()));
|
||||
|
||||
// Set bit W(21)
|
||||
if (ARM_AM::getAM5WBFlag(MO.getImm()))
|
||||
if (IsUpdating)
|
||||
Binary |= 0x1 << ARMII::W_BitShift;
|
||||
|
||||
// First register is encoded in Dd.
|
||||
|
@ -80,8 +80,7 @@ class ARMDAGToDAGISel : public SelectionDAGISel {
|
||||
SDValue &Mode);
|
||||
bool SelectAddrMode5(SDNode *Op, SDValue N, SDValue &Base,
|
||||
SDValue &Offset);
|
||||
bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Update,
|
||||
SDValue &Opc, SDValue &Align);
|
||||
bool SelectAddrMode6(SDNode *Op, SDValue N, SDValue &Addr, SDValue &Align);
|
||||
|
||||
bool SelectAddrModePC(SDNode *Op, SDValue N, SDValue &Offset,
|
||||
SDValue &Label);
|
||||
@ -502,12 +501,8 @@ bool ARMDAGToDAGISel::SelectAddrMode5(SDNode *Op, SDValue N,
|
||||
}
|
||||
|
||||
bool ARMDAGToDAGISel::SelectAddrMode6(SDNode *Op, SDValue N,
|
||||
SDValue &Addr, SDValue &Update,
|
||||
SDValue &Opc, SDValue &Align) {
|
||||
SDValue &Addr, SDValue &Align) {
|
||||
Addr = N;
|
||||
// Default to no writeback.
|
||||
Update = CurDAG->getRegister(0, MVT::i32);
|
||||
Opc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(false), MVT::i32);
|
||||
// Default to no alignment.
|
||||
Align = CurDAG->getTargetConstant(0, MVT::i32);
|
||||
return true;
|
||||
@ -1030,8 +1025,8 @@ SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs,
|
||||
assert(NumVecs >=2 && NumVecs <= 4 && "VLD NumVecs out-of-range");
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
SDValue MemAddr, MemUpdate, MemOpc, Align;
|
||||
if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align))
|
||||
SDValue MemAddr, Align;
|
||||
if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
|
||||
return NULL;
|
||||
|
||||
SDValue Chain = N->getOperand(0);
|
||||
@ -1055,14 +1050,13 @@ SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs,
|
||||
}
|
||||
|
||||
SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
|
||||
SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
|
||||
SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
|
||||
if (is64BitVector) {
|
||||
unsigned Opc = DOpcodes[OpcodeIndex];
|
||||
const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align,
|
||||
Pred, PredReg, Chain };
|
||||
const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain };
|
||||
std::vector<EVT> ResTys(NumVecs, VT);
|
||||
ResTys.push_back(MVT::Other);
|
||||
return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7);
|
||||
return CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5);
|
||||
}
|
||||
|
||||
EVT RegVT = GetNEONSubregVT(VT);
|
||||
@ -1070,11 +1064,10 @@ SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs,
|
||||
// Quad registers are directly supported for VLD2,
|
||||
// loading 2 pairs of D regs.
|
||||
unsigned Opc = QOpcodes0[OpcodeIndex];
|
||||
const SDValue Ops[] = { MemAddr, MemUpdate, MemOpc, Align,
|
||||
Pred, PredReg, Chain };
|
||||
const SDValue Ops[] = { MemAddr, Align, Pred, Reg0, Chain };
|
||||
std::vector<EVT> ResTys(4, VT);
|
||||
ResTys.push_back(MVT::Other);
|
||||
SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 7);
|
||||
SDNode *VLd = CurDAG->getMachineNode(Opc, dl, ResTys, Ops, 5);
|
||||
Chain = SDValue(VLd, 4);
|
||||
|
||||
// Combine the even and odd subregs to produce the result.
|
||||
@ -1086,25 +1079,21 @@ SDNode *ARMDAGToDAGISel::SelectVLD(SDNode *N, unsigned NumVecs,
|
||||
// Otherwise, quad registers are loaded with two separate instructions,
|
||||
// where one loads the even registers and the other loads the odd registers.
|
||||
|
||||
// Enable writeback to the address register.
|
||||
MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32);
|
||||
|
||||
std::vector<EVT> ResTys(NumVecs, RegVT);
|
||||
ResTys.push_back(MemAddr.getValueType());
|
||||
ResTys.push_back(MVT::Other);
|
||||
|
||||
// Load the even subregs.
|
||||
unsigned Opc = QOpcodes0[OpcodeIndex];
|
||||
const SDValue OpsA[] = { MemAddr, MemUpdate, MemOpc, Align,
|
||||
Pred, PredReg, Chain };
|
||||
SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 7);
|
||||
const SDValue OpsA[] = { MemAddr, Align, Reg0, Pred, Reg0, Chain };
|
||||
SDNode *VLdA = CurDAG->getMachineNode(Opc, dl, ResTys, OpsA, 6);
|
||||
Chain = SDValue(VLdA, NumVecs+1);
|
||||
|
||||
// Load the odd subregs.
|
||||
Opc = QOpcodes1[OpcodeIndex];
|
||||
const SDValue OpsB[] = { SDValue(VLdA, NumVecs), MemUpdate, MemOpc,
|
||||
Align, Pred, PredReg, Chain };
|
||||
SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 7);
|
||||
const SDValue OpsB[] = { SDValue(VLdA, NumVecs),
|
||||
Align, Reg0, Pred, Reg0, Chain };
|
||||
SDNode *VLdB = CurDAG->getMachineNode(Opc, dl, ResTys, OpsB, 6);
|
||||
Chain = SDValue(VLdB, NumVecs+1);
|
||||
|
||||
// Combine the even and odd subregs to produce the result.
|
||||
@ -1123,8 +1112,8 @@ SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs,
|
||||
assert(NumVecs >=2 && NumVecs <= 4 && "VST NumVecs out-of-range");
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
SDValue MemAddr, MemUpdate, MemOpc, Align;
|
||||
if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align))
|
||||
SDValue MemAddr, Align;
|
||||
if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
|
||||
return NULL;
|
||||
|
||||
SDValue Chain = N->getOperand(0);
|
||||
@ -1148,12 +1137,10 @@ SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs,
|
||||
}
|
||||
|
||||
SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
|
||||
SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
|
||||
SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
|
||||
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
SmallVector<SDValue, 10> Ops;
|
||||
Ops.push_back(MemAddr);
|
||||
Ops.push_back(MemUpdate);
|
||||
Ops.push_back(MemOpc);
|
||||
Ops.push_back(Align);
|
||||
|
||||
if (is64BitVector) {
|
||||
@ -1161,9 +1148,9 @@ SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs,
|
||||
for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
|
||||
Ops.push_back(N->getOperand(Vec+3));
|
||||
Ops.push_back(Pred);
|
||||
Ops.push_back(PredReg);
|
||||
Ops.push_back(Reg0); // predicate register
|
||||
Ops.push_back(Chain);
|
||||
return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+7);
|
||||
return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+5);
|
||||
}
|
||||
|
||||
EVT RegVT = GetNEONSubregVT(VT);
|
||||
@ -1178,40 +1165,37 @@ SDNode *ARMDAGToDAGISel::SelectVST(SDNode *N, unsigned NumVecs,
|
||||
N->getOperand(Vec+3)));
|
||||
}
|
||||
Ops.push_back(Pred);
|
||||
Ops.push_back(PredReg);
|
||||
Ops.push_back(Reg0); // predicate register
|
||||
Ops.push_back(Chain);
|
||||
return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 11);
|
||||
return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), 9);
|
||||
}
|
||||
|
||||
// Otherwise, quad registers are stored with two separate instructions,
|
||||
// where one stores the even registers and the other stores the odd registers.
|
||||
|
||||
// Enable writeback to the address register.
|
||||
MemOpc = CurDAG->getTargetConstant(ARM_AM::getAM6Opc(true), MVT::i32);
|
||||
Ops.push_back(Reg0); // post-access address offset
|
||||
|
||||
// Store the even subregs.
|
||||
for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
|
||||
Ops.push_back(CurDAG->getTargetExtractSubreg(ARM::DSUBREG_0, dl, RegVT,
|
||||
N->getOperand(Vec+3)));
|
||||
Ops.push_back(Pred);
|
||||
Ops.push_back(PredReg);
|
||||
Ops.push_back(Reg0); // predicate register
|
||||
Ops.push_back(Chain);
|
||||
unsigned Opc = QOpcodes0[OpcodeIndex];
|
||||
SDNode *VStA = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
|
||||
MVT::Other, Ops.data(), NumVecs+7);
|
||||
MVT::Other, Ops.data(), NumVecs+6);
|
||||
Chain = SDValue(VStA, 1);
|
||||
|
||||
// Store the odd subregs.
|
||||
Ops[0] = SDValue(VStA, 0); // MemAddr
|
||||
for (unsigned Vec = 0; Vec < NumVecs; ++Vec)
|
||||
Ops[Vec+4] = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
|
||||
Ops[Vec+3] = CurDAG->getTargetExtractSubreg(ARM::DSUBREG_1, dl, RegVT,
|
||||
N->getOperand(Vec+3));
|
||||
Ops[NumVecs+4] = Pred;
|
||||
Ops[NumVecs+5] = PredReg;
|
||||
Ops[NumVecs+6] = Chain;
|
||||
Ops[NumVecs+5] = Chain;
|
||||
Opc = QOpcodes1[OpcodeIndex];
|
||||
SDNode *VStB = CurDAG->getMachineNode(Opc, dl, MemAddr.getValueType(),
|
||||
MVT::Other, Ops.data(), NumVecs+7);
|
||||
MVT::Other, Ops.data(), NumVecs+6);
|
||||
Chain = SDValue(VStB, 1);
|
||||
ReplaceUses(SDValue(N, 0), Chain);
|
||||
return NULL;
|
||||
@ -1224,8 +1208,8 @@ SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
|
||||
assert(NumVecs >=2 && NumVecs <= 4 && "VLDSTLane NumVecs out-of-range");
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
SDValue MemAddr, MemUpdate, MemOpc, Align;
|
||||
if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, MemUpdate, MemOpc, Align))
|
||||
SDValue MemAddr, Align;
|
||||
if (!SelectAddrMode6(N, N->getOperand(2), MemAddr, Align))
|
||||
return NULL;
|
||||
|
||||
SDValue Chain = N->getOperand(0);
|
||||
@ -1259,12 +1243,10 @@ SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
|
||||
}
|
||||
|
||||
SDValue Pred = CurDAG->getTargetConstant(14, MVT::i32);
|
||||
SDValue PredReg = CurDAG->getRegister(0, MVT::i32);
|
||||
SDValue Reg0 = CurDAG->getRegister(0, MVT::i32);
|
||||
|
||||
SmallVector<SDValue, 9> Ops;
|
||||
SmallVector<SDValue, 10> Ops;
|
||||
Ops.push_back(MemAddr);
|
||||
Ops.push_back(MemUpdate);
|
||||
Ops.push_back(MemOpc);
|
||||
Ops.push_back(Align);
|
||||
|
||||
unsigned Opc = 0;
|
||||
@ -1287,16 +1269,16 @@ SDNode *ARMDAGToDAGISel::SelectVLDSTLane(SDNode *N, bool IsLoad,
|
||||
}
|
||||
Ops.push_back(getI32Imm(Lane));
|
||||
Ops.push_back(Pred);
|
||||
Ops.push_back(PredReg);
|
||||
Ops.push_back(Reg0);
|
||||
Ops.push_back(Chain);
|
||||
|
||||
if (!IsLoad)
|
||||
return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+8);
|
||||
return CurDAG->getMachineNode(Opc, dl, MVT::Other, Ops.data(), NumVecs+6);
|
||||
|
||||
std::vector<EVT> ResTys(NumVecs, RegVT);
|
||||
ResTys.push_back(MVT::Other);
|
||||
SDNode *VLdLn =
|
||||
CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+8);
|
||||
CurDAG->getMachineNode(Opc, dl, ResTys, Ops.data(), NumVecs+6);
|
||||
// For a 64-bit vector load to D registers, nothing more needs to be done.
|
||||
if (is64BitVector)
|
||||
return VLdLn;
|
||||
@ -1859,37 +1841,45 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
|
||||
case Intrinsic::arm_neon_vld3: {
|
||||
unsigned DOpcodes[] = { ARM::VLD3d8, ARM::VLD3d16,
|
||||
ARM::VLD3d32, ARM::VLD3d64 };
|
||||
unsigned QOpcodes0[] = { ARM::VLD3q8a, ARM::VLD3q16a, ARM::VLD3q32a };
|
||||
unsigned QOpcodes1[] = { ARM::VLD3q8b, ARM::VLD3q16b, ARM::VLD3q32b };
|
||||
unsigned QOpcodes0[] = { ARM::VLD3q8_UPD,
|
||||
ARM::VLD3q16_UPD,
|
||||
ARM::VLD3q32_UPD };
|
||||
unsigned QOpcodes1[] = { ARM::VLD3q8odd_UPD,
|
||||
ARM::VLD3q16odd_UPD,
|
||||
ARM::VLD3q32odd_UPD };
|
||||
return SelectVLD(N, 3, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
case Intrinsic::arm_neon_vld4: {
|
||||
unsigned DOpcodes[] = { ARM::VLD4d8, ARM::VLD4d16,
|
||||
ARM::VLD4d32, ARM::VLD4d64 };
|
||||
unsigned QOpcodes0[] = { ARM::VLD4q8a, ARM::VLD4q16a, ARM::VLD4q32a };
|
||||
unsigned QOpcodes1[] = { ARM::VLD4q8b, ARM::VLD4q16b, ARM::VLD4q32b };
|
||||
unsigned QOpcodes0[] = { ARM::VLD4q8_UPD,
|
||||
ARM::VLD4q16_UPD,
|
||||
ARM::VLD4q32_UPD };
|
||||
unsigned QOpcodes1[] = { ARM::VLD4q8odd_UPD,
|
||||
ARM::VLD4q16odd_UPD,
|
||||
ARM::VLD4q32odd_UPD };
|
||||
return SelectVLD(N, 4, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
case Intrinsic::arm_neon_vld2lane: {
|
||||
unsigned DOpcodes[] = { ARM::VLD2LNd8, ARM::VLD2LNd16, ARM::VLD2LNd32 };
|
||||
unsigned QOpcodes0[] = { ARM::VLD2LNq16a, ARM::VLD2LNq32a };
|
||||
unsigned QOpcodes1[] = { ARM::VLD2LNq16b, ARM::VLD2LNq32b };
|
||||
unsigned QOpcodes0[] = { ARM::VLD2LNq16, ARM::VLD2LNq32 };
|
||||
unsigned QOpcodes1[] = { ARM::VLD2LNq16odd, ARM::VLD2LNq32odd };
|
||||
return SelectVLDSTLane(N, true, 2, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
case Intrinsic::arm_neon_vld3lane: {
|
||||
unsigned DOpcodes[] = { ARM::VLD3LNd8, ARM::VLD3LNd16, ARM::VLD3LNd32 };
|
||||
unsigned QOpcodes0[] = { ARM::VLD3LNq16a, ARM::VLD3LNq32a };
|
||||
unsigned QOpcodes1[] = { ARM::VLD3LNq16b, ARM::VLD3LNq32b };
|
||||
unsigned QOpcodes0[] = { ARM::VLD3LNq16, ARM::VLD3LNq32 };
|
||||
unsigned QOpcodes1[] = { ARM::VLD3LNq16odd, ARM::VLD3LNq32odd };
|
||||
return SelectVLDSTLane(N, true, 3, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
case Intrinsic::arm_neon_vld4lane: {
|
||||
unsigned DOpcodes[] = { ARM::VLD4LNd8, ARM::VLD4LNd16, ARM::VLD4LNd32 };
|
||||
unsigned QOpcodes0[] = { ARM::VLD4LNq16a, ARM::VLD4LNq32a };
|
||||
unsigned QOpcodes1[] = { ARM::VLD4LNq16b, ARM::VLD4LNq32b };
|
||||
unsigned QOpcodes0[] = { ARM::VLD4LNq16, ARM::VLD4LNq32 };
|
||||
unsigned QOpcodes1[] = { ARM::VLD4LNq16odd, ARM::VLD4LNq32odd };
|
||||
return SelectVLDSTLane(N, true, 4, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
@ -1903,37 +1893,45 @@ SDNode *ARMDAGToDAGISel::Select(SDNode *N) {
|
||||
case Intrinsic::arm_neon_vst3: {
|
||||
unsigned DOpcodes[] = { ARM::VST3d8, ARM::VST3d16,
|
||||
ARM::VST3d32, ARM::VST3d64 };
|
||||
unsigned QOpcodes0[] = { ARM::VST3q8a, ARM::VST3q16a, ARM::VST3q32a };
|
||||
unsigned QOpcodes1[] = { ARM::VST3q8b, ARM::VST3q16b, ARM::VST3q32b };
|
||||
unsigned QOpcodes0[] = { ARM::VST3q8_UPD,
|
||||
ARM::VST3q16_UPD,
|
||||
ARM::VST3q32_UPD };
|
||||
unsigned QOpcodes1[] = { ARM::VST3q8odd_UPD,
|
||||
ARM::VST3q16odd_UPD,
|
||||
ARM::VST3q32odd_UPD };
|
||||
return SelectVST(N, 3, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
case Intrinsic::arm_neon_vst4: {
|
||||
unsigned DOpcodes[] = { ARM::VST4d8, ARM::VST4d16,
|
||||
ARM::VST4d32, ARM::VST4d64 };
|
||||
unsigned QOpcodes0[] = { ARM::VST4q8a, ARM::VST4q16a, ARM::VST4q32a };
|
||||
unsigned QOpcodes1[] = { ARM::VST4q8b, ARM::VST4q16b, ARM::VST4q32b };
|
||||
unsigned QOpcodes0[] = { ARM::VST4q8_UPD,
|
||||
ARM::VST4q16_UPD,
|
||||
ARM::VST4q32_UPD };
|
||||
unsigned QOpcodes1[] = { ARM::VST4q8odd_UPD,
|
||||
ARM::VST4q16odd_UPD,
|
||||
ARM::VST4q32odd_UPD };
|
||||
return SelectVST(N, 4, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
case Intrinsic::arm_neon_vst2lane: {
|
||||
unsigned DOpcodes[] = { ARM::VST2LNd8, ARM::VST2LNd16, ARM::VST2LNd32 };
|
||||
unsigned QOpcodes0[] = { ARM::VST2LNq16a, ARM::VST2LNq32a };
|
||||
unsigned QOpcodes1[] = { ARM::VST2LNq16b, ARM::VST2LNq32b };
|
||||
unsigned QOpcodes0[] = { ARM::VST2LNq16, ARM::VST2LNq32 };
|
||||
unsigned QOpcodes1[] = { ARM::VST2LNq16odd, ARM::VST2LNq32odd };
|
||||
return SelectVLDSTLane(N, false, 2, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
case Intrinsic::arm_neon_vst3lane: {
|
||||
unsigned DOpcodes[] = { ARM::VST3LNd8, ARM::VST3LNd16, ARM::VST3LNd32 };
|
||||
unsigned QOpcodes0[] = { ARM::VST3LNq16a, ARM::VST3LNq32a };
|
||||
unsigned QOpcodes1[] = { ARM::VST3LNq16b, ARM::VST3LNq32b };
|
||||
unsigned QOpcodes0[] = { ARM::VST3LNq16, ARM::VST3LNq32 };
|
||||
unsigned QOpcodes1[] = { ARM::VST3LNq16odd, ARM::VST3LNq32odd };
|
||||
return SelectVLDSTLane(N, false, 3, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
|
||||
case Intrinsic::arm_neon_vst4lane: {
|
||||
unsigned DOpcodes[] = { ARM::VST4LNd8, ARM::VST4LNd16, ARM::VST4LNd32 };
|
||||
unsigned QOpcodes0[] = { ARM::VST4LNq16a, ARM::VST4LNq32a };
|
||||
unsigned QOpcodes1[] = { ARM::VST4LNq16b, ARM::VST4LNq32b };
|
||||
unsigned QOpcodes0[] = { ARM::VST4LNq16, ARM::VST4LNq32 };
|
||||
unsigned QOpcodes1[] = { ARM::VST4LNq16odd, ARM::VST4LNq32odd };
|
||||
return SelectVLDSTLane(N, false, 4, DOpcodes, QOpcodes0, QOpcodes1);
|
||||
}
|
||||
}
|
||||
|
@ -436,9 +436,9 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
|
||||
}
|
||||
// Special handling for half-precision FP.
|
||||
if (Subtarget->hasVFP3() && Subtarget->hasFP16()) {
|
||||
setOperationAction(ISD::FP16_TO_FP32, MVT::f32, Custom);
|
||||
setOperationAction(ISD::FP32_TO_FP16, MVT::i32, Custom);
|
||||
if (!Subtarget->hasFP16()) {
|
||||
setOperationAction(ISD::FP16_TO_FP32, MVT::f32, Expand);
|
||||
setOperationAction(ISD::FP32_TO_FP16, MVT::i32, Expand);
|
||||
}
|
||||
}
|
||||
|
||||
@ -499,8 +499,6 @@ const char *ARMTargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case ARMISD::FTOUI: return "ARMISD::FTOUI";
|
||||
case ARMISD::SITOF: return "ARMISD::SITOF";
|
||||
case ARMISD::UITOF: return "ARMISD::UITOF";
|
||||
case ARMISD::F16_TO_F32: return "ARMISD::F16_TO_F32";
|
||||
case ARMISD::F32_TO_F16: return "ARMISD::F32_TO_F16";
|
||||
|
||||
case ARMISD::SRL_FLAG: return "ARMISD::SRL_FLAG";
|
||||
case ARMISD::SRA_FLAG: return "ARMISD::SRA_FLAG";
|
||||
@ -1987,9 +1985,6 @@ static SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG) {
|
||||
switch (Op.getOpcode()) {
|
||||
default:
|
||||
assert(0 && "Invalid opcode!");
|
||||
case ISD::FP32_TO_FP16:
|
||||
Opc = ARMISD::F32_TO_F16;
|
||||
break;
|
||||
case ISD::FP_TO_SINT:
|
||||
Opc = ARMISD::FTOSI;
|
||||
break;
|
||||
@ -2009,9 +2004,6 @@ static SDValue LowerINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
|
||||
switch (Op.getOpcode()) {
|
||||
default:
|
||||
assert(0 && "Invalid opcode!");
|
||||
case ISD::FP16_TO_FP32:
|
||||
Opc = ARMISD::F16_TO_F32;
|
||||
break;
|
||||
case ISD::SINT_TO_FP:
|
||||
Opc = ARMISD::SITOF;
|
||||
break;
|
||||
@ -3078,10 +3070,8 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||
case ISD::VASTART: return LowerVASTART(Op, DAG, VarArgsFrameIndex);
|
||||
case ISD::MEMBARRIER: return LowerMEMBARRIER(Op, DAG, Subtarget);
|
||||
case ISD::FP16_TO_FP32:
|
||||
case ISD::SINT_TO_FP:
|
||||
case ISD::UINT_TO_FP: return LowerINT_TO_FP(Op, DAG);
|
||||
case ISD::FP32_TO_FP16:
|
||||
case ISD::FP_TO_SINT:
|
||||
case ISD::FP_TO_UINT: return LowerFP_TO_INT(Op, DAG);
|
||||
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
|
||||
|
@ -59,8 +59,6 @@ namespace llvm {
|
||||
FTOUI, // FP to uint within a FP register.
|
||||
SITOF, // sint to FP within a FP register.
|
||||
UITOF, // uint to FP within a FP register.
|
||||
F16_TO_F32, // Half FP to single FP within a FP register.
|
||||
F32_TO_F16, // Single FP to half FP within a FP register.
|
||||
|
||||
SRL_FLAG, // V,Flag = srl_flag X -> srl X, 1 + save carry out.
|
||||
SRA_FLAG, // V,Flag = sra_flag X -> sra X, 1 + save carry out.
|
||||
|
@ -15,8 +15,8 @@
|
||||
// Format specifies the encoding used by the instruction. This is part of the
|
||||
// ad-hoc solution used to emit machine instruction encodings by our machine
|
||||
// code emitter.
|
||||
class Format<bits<5> val> {
|
||||
bits<5> Value = val;
|
||||
class Format<bits<6> val> {
|
||||
bits<6> Value = val;
|
||||
}
|
||||
|
||||
def Pseudo : Format<0>;
|
||||
@ -33,32 +33,34 @@ def LdMiscFrm : Format<8>;
|
||||
def StMiscFrm : Format<9>;
|
||||
def LdStMulFrm : Format<10>;
|
||||
|
||||
def LdStExFrm : Format<28>;
|
||||
def LdStExFrm : Format<11>;
|
||||
|
||||
def ArithMiscFrm : Format<11>;
|
||||
def ExtFrm : Format<12>;
|
||||
def ArithMiscFrm : Format<12>;
|
||||
def ExtFrm : Format<13>;
|
||||
|
||||
def VFPUnaryFrm : Format<13>;
|
||||
def VFPBinaryFrm : Format<14>;
|
||||
def VFPConv1Frm : Format<15>;
|
||||
def VFPConv2Frm : Format<16>;
|
||||
def VFPConv3Frm : Format<17>;
|
||||
def VFPConv4Frm : Format<18>;
|
||||
def VFPConv5Frm : Format<19>;
|
||||
def VFPLdStFrm : Format<20>;
|
||||
def VFPLdStMulFrm : Format<21>;
|
||||
def VFPMiscFrm : Format<22>;
|
||||
def VFPUnaryFrm : Format<14>;
|
||||
def VFPBinaryFrm : Format<15>;
|
||||
def VFPConv1Frm : Format<16>;
|
||||
def VFPConv2Frm : Format<17>;
|
||||
def VFPConv3Frm : Format<18>;
|
||||
def VFPConv4Frm : Format<19>;
|
||||
def VFPConv5Frm : Format<20>;
|
||||
def VFPLdStFrm : Format<21>;
|
||||
def VFPLdStMulFrm : Format<22>;
|
||||
def VFPMiscFrm : Format<23>;
|
||||
|
||||
def ThumbFrm : Format<23>;
|
||||
def ThumbFrm : Format<24>;
|
||||
|
||||
def NEONFrm : Format<24>;
|
||||
def NEONGetLnFrm : Format<25>;
|
||||
def NEONSetLnFrm : Format<26>;
|
||||
def NEONDupFrm : Format<27>;
|
||||
def NEONFrm : Format<25>;
|
||||
def NEONGetLnFrm : Format<26>;
|
||||
def NEONSetLnFrm : Format<27>;
|
||||
def NEONDupFrm : Format<28>;
|
||||
|
||||
def MiscFrm : Format<29>;
|
||||
def ThumbMiscFrm : Format<30>;
|
||||
|
||||
def NLdStFrm : Format<31>;
|
||||
|
||||
// Misc flags.
|
||||
|
||||
// the instruction has a Rn register operand.
|
||||
@ -71,7 +73,7 @@ class UnaryDP { bit isUnaryDataProc = 1; }
|
||||
class Xform16Bit { bit canXformTo16Bit = 1; }
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ARM Instruction flags. These need to match ARMInstrInfo.h.
|
||||
// ARM Instruction flags. These need to match ARMBaseInstrInfo.h.
|
||||
//
|
||||
|
||||
// Addressing mode.
|
||||
@ -183,7 +185,7 @@ class InstTemplate<AddrMode am, SizeFlagVal sz, IndexMode im,
|
||||
bits<2> IndexModeBits = IM.Value;
|
||||
|
||||
Format F = f;
|
||||
bits<5> Form = F.Value;
|
||||
bits<6> Form = F.Value;
|
||||
|
||||
Domain D = d;
|
||||
bits<2> Dom = D.Value;
|
||||
@ -229,7 +231,7 @@ class I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
list<dag> pattern>
|
||||
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsARM];
|
||||
@ -257,7 +259,7 @@ class sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
list<dag> pattern>
|
||||
: InstARM<am, sz, im, f, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p, cc_out:$s));
|
||||
let InOperandList = !con(iops, (ins pred:$p, cc_out:$s));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}${s}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsARM];
|
||||
@ -1007,8 +1009,8 @@ class Thumb1sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = !con(oops, (ops s_cc_out:$s));
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let OutOperandList = !con(oops, (outs s_cc_out:$s));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsThumb1Only];
|
||||
@ -1030,7 +1032,7 @@ class Thumb1pI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstThumb<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsThumb1Only];
|
||||
@ -1109,7 +1111,7 @@ class Thumb2I<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsThumb2];
|
||||
@ -1125,7 +1127,7 @@ class Thumb2sI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, IndexModeNone, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p, cc_out:$s));
|
||||
let InOperandList = !con(iops, (ins pred:$p, cc_out:$s));
|
||||
let AsmString = !strconcat(opc, !strconcat("${s}${p}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsThumb2];
|
||||
@ -1209,7 +1211,7 @@ class T2Iidxldst<bit signed, bits<2> opcod, bit load, bit pre,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, Size4Bytes, im, ThumbFrm, GenericDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [IsThumb2];
|
||||
@ -1265,7 +1267,7 @@ class VFPI<dag oops, dag iops, AddrMode am, SizeFlagVal sz,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, sz, im, f, VFPDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(opc, !strconcat("${p}", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [HasVFP2];
|
||||
@ -1464,11 +1466,12 @@ class AVConv5I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops,
|
||||
// ARM NEON Instruction templates.
|
||||
//
|
||||
|
||||
class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, Size4Bytes, im, NEONFrm, NeonDomain, cstr, itin> {
|
||||
class NeonI<dag oops, dag iops, AddrMode am, IndexMode im, Format f,
|
||||
InstrItinClass itin, string opc, string dt, string asm, string cstr,
|
||||
list<dag> pattern>
|
||||
: InstARM<am, Size4Bytes, im, f, NeonDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(
|
||||
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
|
||||
!strconcat("\t", asm));
|
||||
@ -1481,7 +1484,7 @@ class NeonXI<dag oops, dag iops, AddrMode am, IndexMode im, InstrItinClass itin,
|
||||
string opc, string asm, string cstr, list<dag> pattern>
|
||||
: InstARM<am, Size4Bytes, im, NEONFrm, NeonDomain, cstr, itin> {
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(!strconcat(opc, "${p}"), !strconcat("\t", asm));
|
||||
let Pattern = pattern;
|
||||
list<Predicate> Predicates = [HasNEON];
|
||||
@ -1502,8 +1505,8 @@ class NI4<dag oops, dag iops, InstrItinClass itin, string opc,
|
||||
class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
|
||||
dag oops, dag iops, InstrItinClass itin,
|
||||
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
||||
: NeonI<oops, iops, AddrMode6, IndexModeNone, itin, opc, dt, asm, cstr,
|
||||
pattern> {
|
||||
: NeonI<oops, iops, AddrMode6, IndexModeNone, NLdStFrm, itin, opc, dt, asm,
|
||||
cstr, pattern> {
|
||||
let Inst{31-24} = 0b11110100;
|
||||
let Inst{23} = op23;
|
||||
let Inst{21-20} = op21_20;
|
||||
@ -1513,7 +1516,7 @@ class NLdSt<bit op23, bits<2> op21_20, bits<4> op11_8, bits<4> op7_4,
|
||||
|
||||
class NDataI<dag oops, dag iops, InstrItinClass itin,
|
||||
string opc, string dt, string asm, string cstr, list<dag> pattern>
|
||||
: NeonI<oops, iops, AddrModeNone, IndexModeNone, itin, opc, dt, asm,
|
||||
: NeonI<oops, iops, AddrModeNone, IndexModeNone, NEONFrm, itin, opc, dt, asm,
|
||||
cstr, pattern> {
|
||||
let Inst{31-25} = 0b1111001;
|
||||
}
|
||||
@ -1621,7 +1624,7 @@ class NVLaneOp<bits<8> opcod1, bits<4> opcod2, bits<2> opcod3,
|
||||
let Inst{4} = 1;
|
||||
|
||||
let OutOperandList = oops;
|
||||
let InOperandList = !con(iops, (ops pred:$p));
|
||||
let InOperandList = !con(iops, (ins pred:$p));
|
||||
let AsmString = !strconcat(
|
||||
!strconcat(!strconcat(opc, "${p}"), !strconcat(".", dt)),
|
||||
!strconcat("\t", asm));
|
||||
|
@ -62,11 +62,14 @@ def ARMcallseq_end : SDNode<"ISD::CALLSEQ_END", SDT_ARMCallSeqEnd,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
|
||||
def ARMcall : SDNode<"ARMISD::CALL", SDT_ARMcall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
def ARMcall_pred : SDNode<"ARMISD::CALL_PRED", SDT_ARMcall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
def ARMcall_nolink : SDNode<"ARMISD::CALL_NOLINK", SDT_ARMcall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
|
||||
def ARMretflag : SDNode<"ARMISD::RET_FLAG", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
@ -282,7 +285,7 @@ def pclabel : Operand<i32> {
|
||||
|
||||
// shifter_operand operands: so_reg and so_imm.
|
||||
def so_reg : Operand<i32>, // reg reg imm
|
||||
ComplexPattern<i32, 3, "SelectShifterOperandReg",
|
||||
ComplexPattern<i32, 3, "SelectShifterOperandReg",
|
||||
[shl,srl,sra,rotr]> {
|
||||
let PrintMethod = "printSORegOperand";
|
||||
let MIOperandInfo = (ops GPR, GPR, i32imm);
|
||||
@ -392,9 +395,14 @@ def addrmode5 : Operand<i32>,
|
||||
// addrmode6 := reg with optional writeback
|
||||
//
|
||||
def addrmode6 : Operand<i32>,
|
||||
ComplexPattern<i32, 4, "SelectAddrMode6", []> {
|
||||
ComplexPattern<i32, 2, "SelectAddrMode6", []> {
|
||||
let PrintMethod = "printAddrMode6Operand";
|
||||
let MIOperandInfo = (ops GPR:$addr, GPR:$upd, i32imm, i32imm);
|
||||
let MIOperandInfo = (ops GPR:$addr, i32imm);
|
||||
}
|
||||
|
||||
def am6offset : Operand<i32> {
|
||||
let PrintMethod = "printAddrMode6OffsetOperand";
|
||||
let MIOperandInfo = (ops GPR);
|
||||
}
|
||||
|
||||
// addrmodepc := pc + reg
|
||||
@ -909,7 +917,7 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
|
||||
def LDM_RET : AXI4ld<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
|
||||
reglist:$dsts, variable_ops),
|
||||
IndexModeUpd, LdStMulFrm, IIC_Br,
|
||||
"ldm${addr:submode}${p}\t$addr, $dsts",
|
||||
"ldm${addr:submode}${p}\t$addr!, $dsts",
|
||||
"$addr.addr = $wb", []>;
|
||||
|
||||
// On non-Darwin platforms R9 is callee-saved.
|
||||
@ -1354,7 +1362,7 @@ def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p,
|
||||
def LDM_UPD : AXI4ld<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
|
||||
reglist:$dsts, variable_ops),
|
||||
IndexModeUpd, LdStMulFrm, IIC_iLoadm,
|
||||
"ldm${addr:submode}${p}\t$addr, $dsts",
|
||||
"ldm${addr:submode}${p}\t$addr!, $dsts",
|
||||
"$addr.addr = $wb", []>;
|
||||
} // mayLoad, hasExtraDefRegAllocReq
|
||||
|
||||
@ -1367,7 +1375,7 @@ def STM : AXI4st<(outs), (ins addrmode4:$addr, pred:$p,
|
||||
def STM_UPD : AXI4st<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
|
||||
reglist:$srcs, variable_ops),
|
||||
IndexModeUpd, LdStMulFrm, IIC_iStorem,
|
||||
"stm${addr:submode}${p}\t$addr, $srcs",
|
||||
"stm${addr:submode}${p}\t$addr!, $srcs",
|
||||
"$addr.addr = $wb", []>;
|
||||
} // mayStore, hasExtraSrcRegAllocReq
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,8 @@
|
||||
//
|
||||
|
||||
def ARMtcall : SDNode<"ARMISD::tCALL", SDT_ARMcall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
|
||||
def imm_neg_XFORM : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant(-(int)N->getZExtValue(), MVT::i32);
|
||||
@ -549,7 +550,7 @@ def tLDM : T1I<(outs),
|
||||
def tLDM_UPD : T1It<(outs tGPR:$wb),
|
||||
(ins addrmode4:$addr, pred:$p, reglist:$dsts, variable_ops),
|
||||
IIC_iLoadm,
|
||||
"ldm${addr:submode}${p}\t$addr, $dsts",
|
||||
"ldm${addr:submode}${p}\t$addr!, $dsts",
|
||||
"$addr.addr = $wb", []>,
|
||||
T1Encoding<{1,1,0,0,1,?}>; // A6.2 & A8.6.53
|
||||
} // mayLoad, hasExtraDefRegAllocReq
|
||||
@ -558,7 +559,7 @@ let mayStore = 1, hasExtraSrcRegAllocReq = 1 in
|
||||
def tSTM_UPD : T1It<(outs tGPR:$wb),
|
||||
(ins addrmode4:$addr, pred:$p, reglist:$srcs, variable_ops),
|
||||
IIC_iStorem,
|
||||
"stm${addr:submode}${p}\t$addr, $srcs",
|
||||
"stm${addr:submode}${p}\t$addr!, $srcs",
|
||||
"$addr.addr = $wb", []>,
|
||||
T1Encoding<{1,1,0,0,0,?}>; // A6.2 & A8.6.189
|
||||
|
||||
|
@ -1218,7 +1218,7 @@ def t2LDM : T2XI<(outs), (ins addrmode4:$addr, pred:$p,
|
||||
|
||||
def t2LDM_UPD : T2XIt<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
|
||||
reglist:$dsts, variable_ops), IIC_iLoadm,
|
||||
"ldm${addr:submode}${p}${addr:wide}\t$addr, $dsts",
|
||||
"ldm${addr:submode}${p}${addr:wide}\t$addr!, $dsts",
|
||||
"$addr.addr = $wb", []> {
|
||||
let Inst{31-27} = 0b11101;
|
||||
let Inst{26-25} = 0b00;
|
||||
@ -1244,7 +1244,7 @@ def t2STM : T2XI<(outs), (ins addrmode4:$addr, pred:$p,
|
||||
def t2STM_UPD : T2XIt<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
|
||||
reglist:$srcs, variable_ops),
|
||||
IIC_iStorem,
|
||||
"stm${addr:submode}${p}${addr:wide}\t$addr, $srcs",
|
||||
"stm${addr:submode}${p}${addr:wide}\t$addr!, $srcs",
|
||||
"$addr.addr = $wb", []> {
|
||||
let Inst{31-27} = 0b11101;
|
||||
let Inst{26-25} = 0b00;
|
||||
|
@ -25,8 +25,6 @@ def arm_ftoui : SDNode<"ARMISD::FTOUI", SDT_FTOI>;
|
||||
def arm_ftosi : SDNode<"ARMISD::FTOSI", SDT_FTOI>;
|
||||
def arm_sitof : SDNode<"ARMISD::SITOF", SDT_ITOF>;
|
||||
def arm_uitof : SDNode<"ARMISD::UITOF", SDT_ITOF>;
|
||||
def arm_f16tof32 : SDNode<"ARMISD::F16_TO_F32", SDT_ITOF>;
|
||||
def arm_f32tof16 : SDNode<"ARMISD::F32_TO_F16", SDT_FTOI>;
|
||||
def arm_fmstat : SDNode<"ARMISD::FMSTAT", SDTNone, [SDNPInFlag,SDNPOutFlag]>;
|
||||
def arm_cmpfp : SDNode<"ARMISD::CMPFP", SDT_ARMCmp, [SDNPOutFlag]>;
|
||||
def arm_cmpfp0 : SDNode<"ARMISD::CMPFPw0",SDT_CMPFP0, [SDNPOutFlag]>;
|
||||
@ -94,7 +92,7 @@ def VLDMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dsts,
|
||||
def VLDMD_UPD : AXDI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
|
||||
reglist:$dsts, variable_ops),
|
||||
IndexModeUpd, IIC_fpLoadm,
|
||||
"vldm${addr:submode}${p}\t${addr:base}, $dsts",
|
||||
"vldm${addr:submode}${p}\t${addr:base}!, $dsts",
|
||||
"$addr.base = $wb", []> {
|
||||
let Inst{20} = 1;
|
||||
}
|
||||
@ -102,7 +100,7 @@ def VLDMD_UPD : AXDI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
|
||||
def VLDMS_UPD : AXSI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
|
||||
reglist:$dsts, variable_ops),
|
||||
IndexModeUpd, IIC_fpLoadm,
|
||||
"vldm${addr:submode}${p}\t${addr:base}, $dsts",
|
||||
"vldm${addr:submode}${p}\t${addr:base}!, $dsts",
|
||||
"$addr.base = $wb", []> {
|
||||
let Inst{20} = 1;
|
||||
}
|
||||
@ -124,7 +122,7 @@ def VSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$srcs,
|
||||
def VSTMD_UPD : AXDI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
|
||||
reglist:$srcs, variable_ops),
|
||||
IndexModeUpd, IIC_fpStorem,
|
||||
"vstm${addr:submode}${p}\t${addr:base}, $srcs",
|
||||
"vstm${addr:submode}${p}\t${addr:base}!, $srcs",
|
||||
"$addr.base = $wb", []> {
|
||||
let Inst{20} = 0;
|
||||
}
|
||||
@ -132,7 +130,7 @@ def VSTMD_UPD : AXDI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
|
||||
def VSTMS_UPD : AXSI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
|
||||
reglist:$srcs, variable_ops),
|
||||
IndexModeUpd, IIC_fpStorem,
|
||||
"vstm${addr:submode}${p}\t${addr:base}, $srcs",
|
||||
"vstm${addr:submode}${p}\t${addr:base}!, $srcs",
|
||||
"$addr.base = $wb", []> {
|
||||
let Inst{20} = 0;
|
||||
}
|
||||
@ -259,11 +257,17 @@ def VCVTSD : VFPAI<(outs SPR:$dst), (ins DPR:$a), VFPUnaryFrm,
|
||||
|
||||
def VCVTBSH : ASuI<0b11101, 0b11, 0b0010, 0b01, 0, (outs SPR:$dst), (ins SPR:$a),
|
||||
/* FIXME */ IIC_fpCVTDS, "vcvtb", ".f32.f16\t$dst, $a",
|
||||
[(set SPR:$dst, (f32 (arm_f32tof16 SPR:$a)))]>;
|
||||
[/* For disassembly only; pattern left blank */]>;
|
||||
|
||||
def : ARMPat<(f32_to_f16 SPR:$a),
|
||||
(i32 (COPY_TO_REGCLASS (VCVTBSH SPR:$a), GPR))>;
|
||||
|
||||
def VCVTBHS : ASuI<0b11101, 0b11, 0b0011, 0b01, 0, (outs SPR:$dst), (ins SPR:$a),
|
||||
/* FIXME */ IIC_fpCVTDS, "vcvtb", ".f16.f32\t$dst, $a",
|
||||
[(set SPR:$dst, (arm_f16tof32 SPR:$a))]>;
|
||||
[/* For disassembly only; pattern left blank */]>;
|
||||
|
||||
def : ARMPat<(f16_to_f32 GPR:$a),
|
||||
(VCVTBHS (COPY_TO_REGCLASS GPR:$a, SPR))>;
|
||||
|
||||
def VCVTTSH : ASuI<0b11101, 0b11, 0b0010, 0b11, 0, (outs SPR:$dst), (ins SPR:$a),
|
||||
/* FIXME */ IIC_fpCVTDS, "vcvtt", ".f32.f16\t$dst, $a",
|
||||
|
@ -253,7 +253,7 @@ ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
|
||||
.addImm(ARM_AM::getAM4ModeImm(Mode)).addImm(Pred).addReg(PredReg)
|
||||
: BuildMI(MBB, MBBI, dl, TII->get(Opcode))
|
||||
.addReg(Base, getKillRegState(BaseKill))
|
||||
.addImm(ARM_AM::getAM5Opc(Mode, false, isDPR ? NumRegs<<1 : NumRegs))
|
||||
.addImm(ARM_AM::getAM5Opc(Mode, isDPR ? NumRegs<<1 : NumRegs))
|
||||
.addImm(Pred).addReg(PredReg);
|
||||
for (unsigned i = 0; i != NumRegs; ++i)
|
||||
MIB = MIB.addReg(Regs[i].first, getDefRegState(isDef)
|
||||
@ -505,11 +505,9 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
||||
if (MI->getOperand(i).getReg() == Base)
|
||||
return false;
|
||||
}
|
||||
assert(!ARM_AM::getAM4WBFlag(MI->getOperand(1).getImm()));
|
||||
Mode = ARM_AM::getAM4SubMode(MI->getOperand(1).getImm());
|
||||
} else {
|
||||
// VLDM{D|S}, VSTM{D|S} addressing mode 5 ops.
|
||||
assert(!ARM_AM::getAM5WBFlag(MI->getOperand(1).getImm()));
|
||||
Mode = ARM_AM::getAM5SubMode(MI->getOperand(1).getImm());
|
||||
Offset = ARM_AM::getAM5Offset(MI->getOperand(1).getImm());
|
||||
}
|
||||
@ -573,11 +571,11 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLSMultiple(MachineBasicBlock &MBB,
|
||||
.addReg(Base, getKillRegState(BaseKill));
|
||||
if (isAM4) {
|
||||
// [t2]LDM_UPD, [t2]STM_UPD
|
||||
MIB.addImm(ARM_AM::getAM4ModeImm(Mode, true))
|
||||
MIB.addImm(ARM_AM::getAM4ModeImm(Mode))
|
||||
.addImm(Pred).addReg(PredReg);
|
||||
} else {
|
||||
// VLDM[SD}_UPD, VSTM[SD]_UPD
|
||||
MIB.addImm(ARM_AM::getAM5Opc(Mode, true, Offset))
|
||||
MIB.addImm(ARM_AM::getAM5Opc(Mode, Offset))
|
||||
.addImm(Pred).addReg(PredReg);
|
||||
}
|
||||
// Transfer the rest of operands.
|
||||
@ -709,7 +707,7 @@ bool ARMLoadStoreOpt::MergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
||||
unsigned Offset = 0;
|
||||
if (isAM5)
|
||||
Offset = ARM_AM::getAM5Opc(AddSub == ARM_AM::sub ? ARM_AM::db : ARM_AM::ia,
|
||||
true, (isDPR ? 2 : 1));
|
||||
(isDPR ? 2 : 1));
|
||||
else if (isAM2)
|
||||
Offset = ARM_AM::getAM2Opc(AddSub, Bytes, ARM_AM::no_shift);
|
||||
else
|
||||
@ -1157,19 +1155,24 @@ namespace {
|
||||
};
|
||||
}
|
||||
|
||||
/// MergeReturnIntoLDM - If this is a exit BB, try merging the return op
|
||||
/// (bx lr) into the preceeding stack restore so it directly restore the value
|
||||
/// of LR into pc.
|
||||
/// ldmfd sp!, {r7, lr}
|
||||
/// MergeReturnIntoLDM - If this is a exit BB, try merging the return ops
|
||||
/// ("bx lr" and "mov pc, lr") into the preceeding stack restore so it
|
||||
/// directly restore the value of LR into pc.
|
||||
/// ldmfd sp!, {..., lr}
|
||||
/// bx lr
|
||||
/// or
|
||||
/// ldmfd sp!, {..., lr}
|
||||
/// mov pc, lr
|
||||
/// =>
|
||||
/// ldmfd sp!, {r7, pc}
|
||||
/// ldmfd sp!, {..., pc}
|
||||
bool ARMLoadStoreOpt::MergeReturnIntoLDM(MachineBasicBlock &MBB) {
|
||||
if (MBB.empty()) return false;
|
||||
|
||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||
if (MBBI != MBB.begin() &&
|
||||
(MBBI->getOpcode() == ARM::BX_RET || MBBI->getOpcode() == ARM::tBX_RET)) {
|
||||
(MBBI->getOpcode() == ARM::BX_RET ||
|
||||
MBBI->getOpcode() == ARM::tBX_RET ||
|
||||
MBBI->getOpcode() == ARM::MOVPCLR)) {
|
||||
MachineInstr *PrevMI = prior(MBBI);
|
||||
if (PrevMI->getOpcode() == ARM::LDM_UPD ||
|
||||
PrevMI->getOpcode() == ARM::t2LDM_UPD) {
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "llvm/Target/TargetRegistry.h"
|
||||
using namespace llvm;
|
||||
|
||||
static const MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
|
||||
static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
|
||||
Triple TheTriple(TT);
|
||||
switch (TheTriple.getOS()) {
|
||||
case Triple::Darwin:
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "ARMISelLowering.h"
|
||||
#include "Thumb1InstrInfo.h"
|
||||
#include "Thumb2InstrInfo.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -83,7 +84,8 @@ class ARMTargetMachine : public ARMBaseTargetMachine {
|
||||
/// Thumb-1 and Thumb-2.
|
||||
///
|
||||
class ThumbTargetMachine : public ARMBaseTargetMachine {
|
||||
ARMBaseInstrInfo *InstrInfo; // either Thumb1InstrInfo or Thumb2InstrInfo
|
||||
// Either Thumb1InstrInfo or Thumb2InstrInfo.
|
||||
OwningPtr<ARMBaseInstrInfo> InstrInfo;
|
||||
const TargetData DataLayout; // Calculates type size & alignment
|
||||
ARMTargetLowering TLInfo;
|
||||
public:
|
||||
@ -100,7 +102,9 @@ class ThumbTargetMachine : public ARMBaseTargetMachine {
|
||||
}
|
||||
|
||||
/// returns either Thumb1InstrInfo or Thumb2InstrInfo
|
||||
virtual const ARMBaseInstrInfo *getInstrInfo() const { return InstrInfo; }
|
||||
virtual const ARMBaseInstrInfo *getInstrInfo() const {
|
||||
return InstrInfo.get();
|
||||
}
|
||||
virtual const TargetData *getTargetData() const { return &DataLayout; }
|
||||
};
|
||||
|
||||
|
@ -101,6 +101,7 @@ namespace {
|
||||
void printAddrMode5Operand(const MachineInstr *MI, int OpNum,
|
||||
const char *Modifier = 0);
|
||||
void printAddrMode6Operand(const MachineInstr *MI, int OpNum);
|
||||
void printAddrMode6OffsetOperand(const MachineInstr *MI, int OpNum);
|
||||
void printAddrModePCOperand(const MachineInstr *MI, int OpNum,
|
||||
const char *Modifier = 0);
|
||||
void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum);
|
||||
@ -431,16 +432,16 @@ void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
if (!MO2.getReg()) {
|
||||
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
||||
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
||||
O << ", #"
|
||||
<< (char)ARM_AM::getAM2Op(MO3.getImm())
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
||||
<< ARM_AM::getAM2Offset(MO3.getImm());
|
||||
O << "]";
|
||||
return;
|
||||
}
|
||||
|
||||
O << ", "
|
||||
<< (char)ARM_AM::getAM2Op(MO3.getImm())
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
||||
<< getRegisterName(MO2.getReg());
|
||||
|
||||
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
|
||||
@ -458,12 +459,12 @@ void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
|
||||
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
|
||||
assert(ImmOffs && "Malformed indexed load / store!");
|
||||
O << "#"
|
||||
<< (char)ARM_AM::getAM2Op(MO2.getImm())
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
||||
<< ImmOffs;
|
||||
return;
|
||||
}
|
||||
|
||||
O << (char)ARM_AM::getAM2Op(MO2.getImm())
|
||||
O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
||||
<< getRegisterName(MO1.getReg());
|
||||
|
||||
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
|
||||
@ -490,7 +491,7 @@ void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
|
||||
|
||||
if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
|
||||
O << ", #"
|
||||
<< (char)ARM_AM::getAM3Op(MO3.getImm())
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
|
||||
<< ImmOffs;
|
||||
O << "]";
|
||||
}
|
||||
@ -508,35 +509,22 @@ void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
|
||||
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
|
||||
assert(ImmOffs && "Malformed indexed load / store!");
|
||||
O << "#"
|
||||
<< (char)ARM_AM::getAM3Op(MO2.getImm())
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
|
||||
<< ImmOffs;
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
|
||||
const char *Modifier) {
|
||||
const MachineOperand &MO1 = MI->getOperand(Op);
|
||||
const MachineOperand &MO2 = MI->getOperand(Op+1);
|
||||
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
|
||||
if (Modifier && strcmp(Modifier, "submode") == 0) {
|
||||
if (MO1.getReg() == ARM::SP) {
|
||||
// FIXME
|
||||
bool isLDM = (MI->getOpcode() == ARM::LDM ||
|
||||
MI->getOpcode() == ARM::LDM_UPD ||
|
||||
MI->getOpcode() == ARM::LDM_RET ||
|
||||
MI->getOpcode() == ARM::t2LDM ||
|
||||
MI->getOpcode() == ARM::t2LDM_UPD ||
|
||||
MI->getOpcode() == ARM::t2LDM_RET);
|
||||
O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
|
||||
} else
|
||||
O << ARM_AM::getAMSubModeStr(Mode);
|
||||
O << ARM_AM::getAMSubModeStr(Mode);
|
||||
} else if (Modifier && strcmp(Modifier, "wide") == 0) {
|
||||
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
|
||||
if (Mode == ARM_AM::ia)
|
||||
O << ".w";
|
||||
} else {
|
||||
printOperand(MI, Op);
|
||||
if (ARM_AM::getAM4WBFlag(MO2.getImm()))
|
||||
O << "!";
|
||||
}
|
||||
}
|
||||
|
||||
@ -559,8 +547,6 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
|
||||
} else if (Modifier && strcmp(Modifier, "base") == 0) {
|
||||
// Used for FSTM{D|S} and LSTM{D|S} operations.
|
||||
O << getRegisterName(MO1.getReg());
|
||||
if (ARM_AM::getAM5WBFlag(MO2.getImm()))
|
||||
O << "!";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -568,7 +554,7 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
|
||||
|
||||
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
|
||||
O << ", #"
|
||||
<< (char)ARM_AM::getAM5Op(MO2.getImm())
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
|
||||
<< ImmOffs*4;
|
||||
}
|
||||
O << "]";
|
||||
@ -577,22 +563,21 @@ void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
|
||||
void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op) {
|
||||
const MachineOperand &MO1 = MI->getOperand(Op);
|
||||
const MachineOperand &MO2 = MI->getOperand(Op+1);
|
||||
const MachineOperand &MO3 = MI->getOperand(Op+2);
|
||||
const MachineOperand &MO4 = MI->getOperand(Op+3);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (MO4.getImm()) {
|
||||
if (MO2.getImm()) {
|
||||
// FIXME: Both darwin as and GNU as violate ARM docs here.
|
||||
O << ", :" << MO4.getImm();
|
||||
O << ", :" << MO2.getImm();
|
||||
}
|
||||
O << "]";
|
||||
}
|
||||
|
||||
if (ARM_AM::getAM6WBFlag(MO3.getImm())) {
|
||||
if (MO2.getReg() == 0)
|
||||
O << "!";
|
||||
else
|
||||
O << ", " << getRegisterName(MO2.getReg());
|
||||
}
|
||||
void ARMAsmPrinter::printAddrMode6OffsetOperand(const MachineInstr *MI, int Op){
|
||||
const MachineOperand &MO = MI->getOperand(Op);
|
||||
if (MO.getReg() == 0)
|
||||
O << "!";
|
||||
else
|
||||
O << ", " << getRegisterName(MO.getReg());
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
|
||||
@ -604,7 +589,7 @@ void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
|
||||
|
||||
const MachineOperand &MO1 = MI->getOperand(Op);
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
|
||||
O << "[pc, +" << getRegisterName(MO1.getReg()) << "]";
|
||||
O << "[pc, " << getRegisterName(MO1.getReg()) << "]";
|
||||
}
|
||||
|
||||
void
|
||||
@ -627,10 +612,11 @@ void
|
||||
ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op) {
|
||||
// (3 - the number of trailing zeros) is the number of then / else.
|
||||
unsigned Mask = MI->getOperand(Op).getImm();
|
||||
unsigned CondBit0 = Mask >> 4 & 1;
|
||||
unsigned NumTZ = CountTrailingZeros_32(Mask);
|
||||
assert(NumTZ <= 3 && "Invalid IT mask!");
|
||||
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
|
||||
bool T = (Mask & (1 << Pos)) == 0;
|
||||
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
||||
if (T)
|
||||
O << 't';
|
||||
else
|
||||
@ -662,7 +648,7 @@ ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
|
||||
if (MO3.getReg())
|
||||
O << ", " << getRegisterName(MO3.getReg());
|
||||
else if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #+" << ImmOffs * Scale;
|
||||
O << ", #" << ImmOffs * Scale;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -684,7 +670,7 @@ void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
|
||||
const MachineOperand &MO2 = MI->getOperand(Op+1);
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #+" << ImmOffs*4;
|
||||
O << ", #" << ImmOffs*4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -720,7 +706,7 @@ void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI,
|
||||
|
||||
unsigned OffImm = MO2.getImm();
|
||||
if (OffImm) // Don't print +0.
|
||||
O << ", #+" << OffImm;
|
||||
O << ", #" << OffImm;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -736,7 +722,7 @@ void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI,
|
||||
if (OffImm < 0)
|
||||
O << ", #-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << ", #+" << OffImm;
|
||||
O << ", #" << OffImm;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -752,7 +738,7 @@ void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI,
|
||||
if (OffImm < 0)
|
||||
O << ", #-" << -OffImm * 4;
|
||||
else if (OffImm > 0)
|
||||
O << ", #+" << OffImm * 4;
|
||||
O << ", #" << OffImm * 4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
@ -764,7 +750,7 @@ void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI,
|
||||
if (OffImm < 0)
|
||||
O << "#-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << "#+" << OffImm;
|
||||
O << "#" << OffImm;
|
||||
}
|
||||
|
||||
void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
|
||||
|
@ -28,7 +28,159 @@ using namespace llvm;
|
||||
#undef MachineInstr
|
||||
#undef ARMAsmPrinter
|
||||
|
||||
void ARMInstPrinter::printInst(const MCInst *MI) { printInstruction(MI); }
|
||||
static unsigned NextReg(unsigned Reg) {
|
||||
switch (Reg) {
|
||||
default:
|
||||
assert(0 && "Unexpected register enum");
|
||||
|
||||
case ARM::D0:
|
||||
return ARM::D1;
|
||||
case ARM::D1:
|
||||
return ARM::D2;
|
||||
case ARM::D2:
|
||||
return ARM::D3;
|
||||
case ARM::D3:
|
||||
return ARM::D4;
|
||||
case ARM::D4:
|
||||
return ARM::D5;
|
||||
case ARM::D5:
|
||||
return ARM::D6;
|
||||
case ARM::D6:
|
||||
return ARM::D7;
|
||||
case ARM::D7:
|
||||
return ARM::D8;
|
||||
case ARM::D8:
|
||||
return ARM::D9;
|
||||
case ARM::D9:
|
||||
return ARM::D10;
|
||||
case ARM::D10:
|
||||
return ARM::D11;
|
||||
case ARM::D11:
|
||||
return ARM::D12;
|
||||
case ARM::D12:
|
||||
return ARM::D13;
|
||||
case ARM::D13:
|
||||
return ARM::D14;
|
||||
case ARM::D14:
|
||||
return ARM::D15;
|
||||
case ARM::D15:
|
||||
return ARM::D16;
|
||||
case ARM::D16:
|
||||
return ARM::D17;
|
||||
case ARM::D17:
|
||||
return ARM::D18;
|
||||
case ARM::D18:
|
||||
return ARM::D19;
|
||||
case ARM::D19:
|
||||
return ARM::D20;
|
||||
case ARM::D20:
|
||||
return ARM::D21;
|
||||
case ARM::D21:
|
||||
return ARM::D22;
|
||||
case ARM::D22:
|
||||
return ARM::D23;
|
||||
case ARM::D23:
|
||||
return ARM::D24;
|
||||
case ARM::D24:
|
||||
return ARM::D25;
|
||||
case ARM::D25:
|
||||
return ARM::D26;
|
||||
case ARM::D26:
|
||||
return ARM::D27;
|
||||
case ARM::D27:
|
||||
return ARM::D28;
|
||||
case ARM::D28:
|
||||
return ARM::D29;
|
||||
case ARM::D29:
|
||||
return ARM::D30;
|
||||
case ARM::D30:
|
||||
return ARM::D31;
|
||||
}
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printInst(const MCInst *MI) {
|
||||
// Check for MOVs and print canonical forms, instead.
|
||||
if (MI->getOpcode() == ARM::MOVs) {
|
||||
const MCOperand &Dst = MI->getOperand(0);
|
||||
const MCOperand &MO1 = MI->getOperand(1);
|
||||
const MCOperand &MO2 = MI->getOperand(2);
|
||||
const MCOperand &MO3 = MI->getOperand(3);
|
||||
|
||||
O << '\t' << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()));
|
||||
printSBitModifierOperand(MI, 6);
|
||||
printPredicateOperand(MI, 4);
|
||||
|
||||
O << '\t' << getRegisterName(Dst.getReg())
|
||||
<< ", " << getRegisterName(MO1.getReg());
|
||||
|
||||
if (ARM_AM::getSORegShOp(MO3.getImm()) == ARM_AM::rrx)
|
||||
return;
|
||||
|
||||
O << ", ";
|
||||
|
||||
if (MO2.getReg()) {
|
||||
O << getRegisterName(MO2.getReg());
|
||||
assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
|
||||
} else {
|
||||
O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// A8.6.123 PUSH
|
||||
if ((MI->getOpcode() == ARM::STM_UPD || MI->getOpcode() == ARM::t2STM_UPD) &&
|
||||
MI->getOperand(0).getReg() == ARM::SP) {
|
||||
const MCOperand &MO1 = MI->getOperand(2);
|
||||
if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::db) {
|
||||
O << '\t' << "push";
|
||||
printPredicateOperand(MI, 3);
|
||||
O << '\t';
|
||||
printRegisterList(MI, 5);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// A8.6.122 POP
|
||||
if ((MI->getOpcode() == ARM::LDM_UPD || MI->getOpcode() == ARM::t2LDM_UPD) &&
|
||||
MI->getOperand(0).getReg() == ARM::SP) {
|
||||
const MCOperand &MO1 = MI->getOperand(2);
|
||||
if (ARM_AM::getAM4SubMode(MO1.getImm()) == ARM_AM::ia) {
|
||||
O << '\t' << "pop";
|
||||
printPredicateOperand(MI, 3);
|
||||
O << '\t';
|
||||
printRegisterList(MI, 5);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// A8.6.355 VPUSH
|
||||
if ((MI->getOpcode() == ARM::VSTMS_UPD || MI->getOpcode() ==ARM::VSTMD_UPD) &&
|
||||
MI->getOperand(0).getReg() == ARM::SP) {
|
||||
const MCOperand &MO1 = MI->getOperand(2);
|
||||
if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::db) {
|
||||
O << '\t' << "vpush";
|
||||
printPredicateOperand(MI, 3);
|
||||
O << '\t';
|
||||
printRegisterList(MI, 5);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// A8.6.354 VPOP
|
||||
if ((MI->getOpcode() == ARM::VLDMS_UPD || MI->getOpcode() ==ARM::VLDMD_UPD) &&
|
||||
MI->getOperand(0).getReg() == ARM::SP) {
|
||||
const MCOperand &MO1 = MI->getOperand(2);
|
||||
if (ARM_AM::getAM5SubMode(MO1.getImm()) == ARM_AM::ia) {
|
||||
O << '\t' << "vpop";
|
||||
printPredicateOperand(MI, 3);
|
||||
O << '\t';
|
||||
printRegisterList(MI, 5);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
printInstruction(MI);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
const char *Modifier) {
|
||||
@ -36,6 +188,9 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
if (Op.isReg()) {
|
||||
unsigned Reg = Op.getReg();
|
||||
if (Modifier && strcmp(Modifier, "dregpair") == 0) {
|
||||
O << '{' << getRegisterName(Reg) << ", "
|
||||
<< getRegisterName(NextReg(Reg)) << '}';
|
||||
#if 0
|
||||
// FIXME: Breaks e.g. ARM/vmul.ll.
|
||||
assert(0);
|
||||
/*
|
||||
@ -44,6 +199,7 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
O << '{'
|
||||
<< getRegisterName(DRegLo) << ',' << getRegisterName(DRegHi)
|
||||
<< '}';*/
|
||||
#endif
|
||||
} else if (Modifier && strcmp(Modifier, "lane") == 0) {
|
||||
assert(0);
|
||||
/*
|
||||
@ -56,7 +212,8 @@ void ARMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
|
||||
O << getRegisterName(Reg);
|
||||
}
|
||||
} else if (Op.isImm()) {
|
||||
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
|
||||
assert((Modifier && !strcmp(Modifier, "call")) ||
|
||||
((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"));
|
||||
O << '#' << Op.getImm();
|
||||
} else {
|
||||
assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported");
|
||||
@ -142,17 +299,17 @@ void ARMInstPrinter::printAddrMode2Operand(const MCInst *MI, unsigned Op) {
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
if (!MO2.getReg()) {
|
||||
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
||||
if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
|
||||
O << ", #"
|
||||
<< (char)ARM_AM::getAM2Op(MO3.getImm())
|
||||
<< ARM_AM::getAM2Offset(MO3.getImm());
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
||||
<< ARM_AM::getAM2Offset(MO3.getImm());
|
||||
O << "]";
|
||||
return;
|
||||
}
|
||||
|
||||
O << ", "
|
||||
<< (char)ARM_AM::getAM2Op(MO3.getImm())
|
||||
<< getRegisterName(MO2.getReg());
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
|
||||
<< getRegisterName(MO2.getReg());
|
||||
|
||||
if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
|
||||
O << ", "
|
||||
@ -169,11 +326,14 @@ void ARMInstPrinter::printAddrMode2OffsetOperand(const MCInst *MI,
|
||||
if (!MO1.getReg()) {
|
||||
unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
|
||||
assert(ImmOffs && "Malformed indexed load / store!");
|
||||
O << '#' << (char)ARM_AM::getAM2Op(MO2.getImm()) << ImmOffs;
|
||||
O << '#'
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
||||
<< ImmOffs;
|
||||
return;
|
||||
}
|
||||
|
||||
O << (char)ARM_AM::getAM2Op(MO2.getImm()) << getRegisterName(MO1.getReg());
|
||||
O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
|
||||
<< getRegisterName(MO1.getReg());
|
||||
|
||||
if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
|
||||
O << ", "
|
||||
@ -196,8 +356,8 @@ void ARMInstPrinter::printAddrMode3Operand(const MCInst *MI, unsigned OpNum) {
|
||||
|
||||
if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
|
||||
O << ", #"
|
||||
<< (char)ARM_AM::getAM3Op(MO3.getImm())
|
||||
<< ImmOffs;
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
|
||||
<< ImmOffs;
|
||||
O << ']';
|
||||
}
|
||||
|
||||
@ -214,35 +374,24 @@ void ARMInstPrinter::printAddrMode3OffsetOperand(const MCInst *MI,
|
||||
|
||||
unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
|
||||
assert(ImmOffs && "Malformed indexed load / store!");
|
||||
O << "#"
|
||||
<< (char)ARM_AM::getAM3Op(MO2.getImm())
|
||||
<< ImmOffs;
|
||||
O << '#'
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
|
||||
<< ImmOffs;
|
||||
}
|
||||
|
||||
|
||||
void ARMInstPrinter::printAddrMode4Operand(const MCInst *MI, unsigned OpNum,
|
||||
const char *Modifier) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
|
||||
if (Modifier && strcmp(Modifier, "submode") == 0) {
|
||||
if (MO1.getReg() == ARM::SP) {
|
||||
// FIXME
|
||||
bool isLDM = (MI->getOpcode() == ARM::LDM ||
|
||||
MI->getOpcode() == ARM::LDM_RET ||
|
||||
MI->getOpcode() == ARM::t2LDM ||
|
||||
MI->getOpcode() == ARM::t2LDM_RET);
|
||||
O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
|
||||
} else
|
||||
O << ARM_AM::getAMSubModeStr(Mode);
|
||||
O << ARM_AM::getAMSubModeStr(Mode);
|
||||
} else if (Modifier && strcmp(Modifier, "wide") == 0) {
|
||||
ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
|
||||
if (Mode == ARM_AM::ia)
|
||||
O << ".w";
|
||||
} else {
|
||||
printOperand(MI, OpNum);
|
||||
if (ARM_AM::getAM4WBFlag(MO2.getImm()))
|
||||
O << "!";
|
||||
}
|
||||
}
|
||||
|
||||
@ -263,8 +412,6 @@ void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
|
||||
} else if (Modifier && strcmp(Modifier, "base") == 0) {
|
||||
// Used for FSTM{D|S} and LSTM{D|S} operations.
|
||||
O << getRegisterName(MO1.getReg());
|
||||
if (ARM_AM::getAM5WBFlag(MO2.getImm()))
|
||||
O << "!";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -272,7 +419,7 @@ void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
|
||||
|
||||
if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
|
||||
O << ", #"
|
||||
<< (char)ARM_AM::getAM5Op(MO2.getImm())
|
||||
<< ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
|
||||
<< ImmOffs*4;
|
||||
}
|
||||
O << "]";
|
||||
@ -281,17 +428,22 @@ void ARMInstPrinter::printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
|
||||
void ARMInstPrinter::printAddrMode6Operand(const MCInst *MI, unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
const MCOperand &MO3 = MI->getOperand(OpNum+2);
|
||||
|
||||
// FIXME: No support yet for specifying alignment.
|
||||
O << '[' << getRegisterName(MO1.getReg()) << ']';
|
||||
|
||||
if (ARM_AM::getAM6WBFlag(MO3.getImm())) {
|
||||
if (MO2.getReg() == 0)
|
||||
O << '!';
|
||||
else
|
||||
O << ", " << getRegisterName(MO2.getReg());
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (MO2.getImm()) {
|
||||
// FIXME: Both darwin as and GNU as violate ARM docs here.
|
||||
O << ", :" << MO2.getImm();
|
||||
}
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printAddrMode6OffsetOperand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO = MI->getOperand(OpNum);
|
||||
if (MO.getReg() == 0)
|
||||
O << "!";
|
||||
else
|
||||
O << ", " << getRegisterName(MO.getReg());
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
|
||||
@ -311,14 +463,56 @@ void ARMInstPrinter::printBitfieldInvMaskImmOperand (const MCInst *MI,
|
||||
|
||||
void ARMInstPrinter::printRegisterList(const MCInst *MI, unsigned OpNum) {
|
||||
O << "{";
|
||||
// Always skip the first operand, it's the optional (and implicit writeback).
|
||||
for (unsigned i = OpNum+1, e = MI->getNumOperands(); i != e; ++i) {
|
||||
if (i != OpNum+1) O << ", ";
|
||||
for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
|
||||
if (i != OpNum) O << ", ";
|
||||
O << getRegisterName(MI->getOperand(i).getReg());
|
||||
}
|
||||
O << "}";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printCPSOptionOperand(const MCInst *MI, unsigned OpNum) {
|
||||
const MCOperand &Op = MI->getOperand(OpNum);
|
||||
unsigned option = Op.getImm();
|
||||
unsigned mode = option & 31;
|
||||
bool changemode = option >> 5 & 1;
|
||||
unsigned AIF = option >> 6 & 7;
|
||||
unsigned imod = option >> 9 & 3;
|
||||
if (imod == 2)
|
||||
O << "ie";
|
||||
else if (imod == 3)
|
||||
O << "id";
|
||||
O << '\t';
|
||||
if (imod > 1) {
|
||||
if (AIF & 4) O << 'a';
|
||||
if (AIF & 2) O << 'i';
|
||||
if (AIF & 1) O << 'f';
|
||||
if (AIF > 0 && changemode) O << ", ";
|
||||
}
|
||||
if (changemode)
|
||||
O << '#' << mode;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printMSRMaskOperand(const MCInst *MI, unsigned OpNum) {
|
||||
const MCOperand &Op = MI->getOperand(OpNum);
|
||||
unsigned Mask = Op.getImm();
|
||||
if (Mask) {
|
||||
O << '_';
|
||||
if (Mask & 8) O << 'f';
|
||||
if (Mask & 4) O << 's';
|
||||
if (Mask & 2) O << 'x';
|
||||
if (Mask & 1) O << 'c';
|
||||
}
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printNegZeroOperand(const MCInst *MI, unsigned OpNum){
|
||||
const MCOperand &Op = MI->getOperand(OpNum);
|
||||
O << '#';
|
||||
if (Op.getImm() < 0)
|
||||
O << '-' << (-Op.getImm() - 1);
|
||||
else
|
||||
O << Op.getImm();
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printPredicateOperand(const MCInst *MI, unsigned OpNum) {
|
||||
ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
|
||||
if (CC != ARMCC::AL)
|
||||
@ -360,3 +554,191 @@ void ARMInstPrinter::printPCLabel(const MCInst *MI, unsigned OpNum) {
|
||||
void ARMInstPrinter::printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum) {
|
||||
O << "#" << MI->getOperand(OpNum).getImm() * 4;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbITMask(const MCInst *MI, unsigned OpNum) {
|
||||
// (3 - the number of trailing zeros) is the number of then / else.
|
||||
unsigned Mask = MI->getOperand(OpNum).getImm();
|
||||
unsigned CondBit0 = Mask >> 4 & 1;
|
||||
unsigned NumTZ = CountTrailingZeros_32(Mask);
|
||||
assert(NumTZ <= 3 && "Invalid IT mask!");
|
||||
for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
|
||||
bool T = ((Mask >> Pos) & 1) == CondBit0;
|
||||
if (T)
|
||||
O << 't';
|
||||
else
|
||||
O << 'e';
|
||||
}
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeRROperand(const MCInst *MI, unsigned Op)
|
||||
{
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
O << ", " << getRegisterName(MO2.getReg()) << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeRI5Operand(const MCInst *MI, unsigned Op,
|
||||
unsigned Scale) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
const MCOperand &MO3 = MI->getOperand(Op+2);
|
||||
|
||||
if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
|
||||
printOperand(MI, Op);
|
||||
return;
|
||||
}
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (MO3.getReg())
|
||||
O << ", " << getRegisterName(MO3.getReg());
|
||||
else if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #" << ImmOffs * Scale;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS1Operand(const MCInst *MI, unsigned Op)
|
||||
{
|
||||
printThumbAddrModeRI5Operand(MI, Op, 1);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS2Operand(const MCInst *MI, unsigned Op)
|
||||
{
|
||||
printThumbAddrModeRI5Operand(MI, Op, 2);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeS4Operand(const MCInst *MI, unsigned Op)
|
||||
{
|
||||
printThumbAddrModeRI5Operand(MI, Op, 4);
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printThumbAddrModeSPOperand(const MCInst *MI,unsigned Op) {
|
||||
const MCOperand &MO1 = MI->getOperand(Op);
|
||||
const MCOperand &MO2 = MI->getOperand(Op+1);
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
if (unsigned ImmOffs = MO2.getImm())
|
||||
O << ", #" << ImmOffs*4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printTBAddrMode(const MCInst *MI, unsigned OpNum) {
|
||||
O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
|
||||
if (MI->getOpcode() == ARM::t2TBH)
|
||||
O << ", lsl #1";
|
||||
O << ']';
|
||||
}
|
||||
|
||||
// Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
|
||||
// register with shift forms.
|
||||
// REG 0 0 - e.g. R5
|
||||
// REG IMM, SH_OPC - e.g. R5, LSL #3
|
||||
void ARMInstPrinter::printT2SOOperand(const MCInst *MI, unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
unsigned Reg = MO1.getReg();
|
||||
O << getRegisterName(Reg);
|
||||
|
||||
// Print the shift opc.
|
||||
O << ", "
|
||||
<< ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
|
||||
<< " ";
|
||||
|
||||
assert(MO2.isImm() && "Not a valid t2_so_reg value!");
|
||||
O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm12Operand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
unsigned OffImm = MO2.getImm();
|
||||
if (OffImm) // Don't print +0.
|
||||
O << ", #" << OffImm;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8Operand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
int32_t OffImm = (int32_t)MO2.getImm();
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << ", #-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << ", #" << OffImm;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8s4Operand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
int32_t OffImm = (int32_t)MO2.getImm() / 4;
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << ", #-" << -OffImm * 4;
|
||||
else if (OffImm > 0)
|
||||
O << ", #" << OffImm * 4;
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8OffsetOperand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
int32_t OffImm = (int32_t)MO1.getImm();
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << "#-" << -OffImm;
|
||||
else if (OffImm > 0)
|
||||
O << "#" << OffImm;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeImm8s4OffsetOperand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
int32_t OffImm = (int32_t)MO1.getImm() / 4;
|
||||
// Don't print +0.
|
||||
if (OffImm < 0)
|
||||
O << "#-" << -OffImm * 4;
|
||||
else if (OffImm > 0)
|
||||
O << "#" << OffImm * 4;
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printT2AddrModeSoRegOperand(const MCInst *MI,
|
||||
unsigned OpNum) {
|
||||
const MCOperand &MO1 = MI->getOperand(OpNum);
|
||||
const MCOperand &MO2 = MI->getOperand(OpNum+1);
|
||||
const MCOperand &MO3 = MI->getOperand(OpNum+2);
|
||||
|
||||
O << "[" << getRegisterName(MO1.getReg());
|
||||
|
||||
assert(MO2.getReg() && "Invalid so_reg load / store address!");
|
||||
O << ", " << getRegisterName(MO2.getReg());
|
||||
|
||||
unsigned ShAmt = MO3.getImm();
|
||||
if (ShAmt) {
|
||||
assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
|
||||
O << ", lsl #" << ShAmt;
|
||||
}
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum) {
|
||||
O << '#' << MI->getOperand(OpNum).getImm();
|
||||
}
|
||||
|
||||
void ARMInstPrinter::printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum) {
|
||||
O << '#' << MI->getOperand(OpNum).getImm();
|
||||
}
|
||||
|
||||
|
@ -48,32 +48,33 @@ class ARMInstPrinter : public MCInstPrinter {
|
||||
void printAddrMode5Operand(const MCInst *MI, unsigned OpNum,
|
||||
const char *Modifier = 0);
|
||||
void printAddrMode6Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printAddrMode6OffsetOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printAddrModePCOperand(const MCInst *MI, unsigned OpNum,
|
||||
const char *Modifier = 0);
|
||||
|
||||
void printBitfieldInvMaskImmOperand(const MCInst *MI, unsigned OpNum);
|
||||
|
||||
void printThumbS4ImmOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbITMask(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbITMask(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeRROperand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeRI5Operand(const MCInst *MI, unsigned OpNum,
|
||||
unsigned Scale) {}
|
||||
void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
unsigned Scale);
|
||||
void printThumbAddrModeS1Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeS2Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeS4Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printThumbAddrModeSPOperand(const MCInst *MI, unsigned OpNum);
|
||||
|
||||
void printT2SOOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printT2SOOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm12Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm8Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm8s4Operand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm8OffsetOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeImm8s4OffsetOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printT2AddrModeSoRegOperand(const MCInst *MI, unsigned OpNum);
|
||||
|
||||
void printCPSOptionOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printMSRMaskOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printNegZeroOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printCPSOptionOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printMSRMaskOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printNegZeroOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printPredicateOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printMandatoryPredicateOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printSBitModifierOperand(const MCInst *MI, unsigned OpNum);
|
||||
@ -82,10 +83,10 @@ class ARMInstPrinter : public MCInstPrinter {
|
||||
const char *Modifier);
|
||||
void printJTBlockOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printJT2BlockOperand(const MCInst *MI, unsigned OpNum) {}
|
||||
void printTBAddrMode(const MCInst *MI, unsigned OpNum) {}
|
||||
void printTBAddrMode(const MCInst *MI, unsigned OpNum);
|
||||
void printNoHashImmediate(const MCInst *MI, unsigned OpNum);
|
||||
void printVFPf32ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printVFPf64ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printVFPf32ImmOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printVFPf64ImmOperand(const MCInst *MI, unsigned OpNum);
|
||||
void printHex8ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printHex16ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
void printHex32ImmOperand(const MCInst *MI, int OpNum) {}
|
||||
|
@ -64,16 +64,16 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs,
|
||||
NumRegs = 4;
|
||||
return true;
|
||||
|
||||
case ARM::VLD2LNq16a:
|
||||
case ARM::VLD2LNq32a:
|
||||
case ARM::VLD2LNq16:
|
||||
case ARM::VLD2LNq32:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 2;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VLD2LNq16b:
|
||||
case ARM::VLD2LNq32b:
|
||||
case ARM::VLD2LNq16odd:
|
||||
case ARM::VLD2LNq32odd:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 2;
|
||||
Offset = 1;
|
||||
@ -91,34 +91,34 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs,
|
||||
NumRegs = 3;
|
||||
return true;
|
||||
|
||||
case ARM::VLD3q8a:
|
||||
case ARM::VLD3q16a:
|
||||
case ARM::VLD3q32a:
|
||||
case ARM::VLD3q8_UPD:
|
||||
case ARM::VLD3q16_UPD:
|
||||
case ARM::VLD3q32_UPD:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 3;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VLD3q8b:
|
||||
case ARM::VLD3q16b:
|
||||
case ARM::VLD3q32b:
|
||||
case ARM::VLD3q8odd_UPD:
|
||||
case ARM::VLD3q16odd_UPD:
|
||||
case ARM::VLD3q32odd_UPD:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 3;
|
||||
Offset = 1;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VLD3LNq16a:
|
||||
case ARM::VLD3LNq32a:
|
||||
case ARM::VLD3LNq16:
|
||||
case ARM::VLD3LNq32:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 3;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VLD3LNq16b:
|
||||
case ARM::VLD3LNq32b:
|
||||
case ARM::VLD3LNq16odd:
|
||||
case ARM::VLD3LNq32odd:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 3;
|
||||
Offset = 1;
|
||||
@ -136,34 +136,34 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs,
|
||||
NumRegs = 4;
|
||||
return true;
|
||||
|
||||
case ARM::VLD4q8a:
|
||||
case ARM::VLD4q16a:
|
||||
case ARM::VLD4q32a:
|
||||
case ARM::VLD4q8_UPD:
|
||||
case ARM::VLD4q16_UPD:
|
||||
case ARM::VLD4q32_UPD:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 4;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VLD4q8b:
|
||||
case ARM::VLD4q16b:
|
||||
case ARM::VLD4q32b:
|
||||
case ARM::VLD4q8odd_UPD:
|
||||
case ARM::VLD4q16odd_UPD:
|
||||
case ARM::VLD4q32odd_UPD:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 4;
|
||||
Offset = 1;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VLD4LNq16a:
|
||||
case ARM::VLD4LNq32a:
|
||||
case ARM::VLD4LNq16:
|
||||
case ARM::VLD4LNq32:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 4;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VLD4LNq16b:
|
||||
case ARM::VLD4LNq32b:
|
||||
case ARM::VLD4LNq16odd:
|
||||
case ARM::VLD4LNq32odd:
|
||||
FirstOpnd = 0;
|
||||
NumRegs = 4;
|
||||
Offset = 1;
|
||||
@ -177,28 +177,28 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs,
|
||||
case ARM::VST2LNd8:
|
||||
case ARM::VST2LNd16:
|
||||
case ARM::VST2LNd32:
|
||||
FirstOpnd = 4;
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VST2q8:
|
||||
case ARM::VST2q16:
|
||||
case ARM::VST2q32:
|
||||
FirstOpnd = 4;
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 4;
|
||||
return true;
|
||||
|
||||
case ARM::VST2LNq16a:
|
||||
case ARM::VST2LNq32a:
|
||||
FirstOpnd = 4;
|
||||
case ARM::VST2LNq16:
|
||||
case ARM::VST2LNq32:
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 2;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VST2LNq16b:
|
||||
case ARM::VST2LNq32b:
|
||||
FirstOpnd = 4;
|
||||
case ARM::VST2LNq16odd:
|
||||
case ARM::VST2LNq32odd:
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 2;
|
||||
Offset = 1;
|
||||
Stride = 2;
|
||||
@ -211,39 +211,39 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs,
|
||||
case ARM::VST3LNd8:
|
||||
case ARM::VST3LNd16:
|
||||
case ARM::VST3LNd32:
|
||||
FirstOpnd = 4;
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 3;
|
||||
return true;
|
||||
|
||||
case ARM::VST3q8a:
|
||||
case ARM::VST3q16a:
|
||||
case ARM::VST3q32a:
|
||||
FirstOpnd = 5;
|
||||
case ARM::VST3q8_UPD:
|
||||
case ARM::VST3q16_UPD:
|
||||
case ARM::VST3q32_UPD:
|
||||
FirstOpnd = 4;
|
||||
NumRegs = 3;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VST3q8b:
|
||||
case ARM::VST3q16b:
|
||||
case ARM::VST3q32b:
|
||||
FirstOpnd = 5;
|
||||
case ARM::VST3q8odd_UPD:
|
||||
case ARM::VST3q16odd_UPD:
|
||||
case ARM::VST3q32odd_UPD:
|
||||
FirstOpnd = 4;
|
||||
NumRegs = 3;
|
||||
Offset = 1;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VST3LNq16a:
|
||||
case ARM::VST3LNq32a:
|
||||
FirstOpnd = 4;
|
||||
case ARM::VST3LNq16:
|
||||
case ARM::VST3LNq32:
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 3;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VST3LNq16b:
|
||||
case ARM::VST3LNq32b:
|
||||
FirstOpnd = 4;
|
||||
case ARM::VST3LNq16odd:
|
||||
case ARM::VST3LNq32odd:
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 3;
|
||||
Offset = 1;
|
||||
Stride = 2;
|
||||
@ -256,39 +256,39 @@ static bool isNEONMultiRegOp(int Opcode, unsigned &FirstOpnd, unsigned &NumRegs,
|
||||
case ARM::VST4LNd8:
|
||||
case ARM::VST4LNd16:
|
||||
case ARM::VST4LNd32:
|
||||
FirstOpnd = 4;
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 4;
|
||||
return true;
|
||||
|
||||
case ARM::VST4q8a:
|
||||
case ARM::VST4q16a:
|
||||
case ARM::VST4q32a:
|
||||
FirstOpnd = 5;
|
||||
case ARM::VST4q8_UPD:
|
||||
case ARM::VST4q16_UPD:
|
||||
case ARM::VST4q32_UPD:
|
||||
FirstOpnd = 4;
|
||||
NumRegs = 4;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VST4q8b:
|
||||
case ARM::VST4q16b:
|
||||
case ARM::VST4q32b:
|
||||
FirstOpnd = 5;
|
||||
case ARM::VST4q8odd_UPD:
|
||||
case ARM::VST4q16odd_UPD:
|
||||
case ARM::VST4q32odd_UPD:
|
||||
FirstOpnd = 4;
|
||||
NumRegs = 4;
|
||||
Offset = 1;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VST4LNq16a:
|
||||
case ARM::VST4LNq32a:
|
||||
FirstOpnd = 4;
|
||||
case ARM::VST4LNq16:
|
||||
case ARM::VST4LNq32:
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 4;
|
||||
Offset = 0;
|
||||
Stride = 2;
|
||||
return true;
|
||||
|
||||
case ARM::VST4LNq16b:
|
||||
case ARM::VST4LNq32b:
|
||||
FirstOpnd = 4;
|
||||
case ARM::VST4LNq16odd:
|
||||
case ARM::VST4LNq32odd:
|
||||
FirstOpnd = 2;
|
||||
NumRegs = 4;
|
||||
Offset = 1;
|
||||
Stride = 2;
|
||||
|
@ -78,14 +78,16 @@ bool Thumb2ITBlockPass::InsertITBlocks(MachineBasicBlock &MBB) {
|
||||
DebugLoc ndl = NMI->getDebugLoc();
|
||||
unsigned NPredReg = 0;
|
||||
ARMCC::CondCodes NCC = getPredicate(NMI, NPredReg);
|
||||
if (NCC == OCC) {
|
||||
Mask |= (1 << Pos);
|
||||
} else if (NCC != CC)
|
||||
if (NCC == CC || NCC == OCC)
|
||||
Mask |= (NCC & 1) << Pos;
|
||||
else
|
||||
break;
|
||||
--Pos;
|
||||
++MBBI;
|
||||
}
|
||||
Mask |= (1 << Pos);
|
||||
// Tag along (firstcond[0] << 4) with the mask.
|
||||
Mask |= (CC & 1) << 4;
|
||||
MIB.addImm(Mask);
|
||||
Modified = true;
|
||||
++NumITs;
|
||||
|
@ -56,16 +56,16 @@ class MfcForm<bits<6> opcode, bits<16> fc, string asmstr, InstrItinClass itin>
|
||||
: InstAlpha<opcode, asmstr, itin> {
|
||||
bits<5> Ra;
|
||||
|
||||
let OutOperandList = (ops GPRC:$RA);
|
||||
let InOperandList = (ops);
|
||||
let OutOperandList = (outs GPRC:$RA);
|
||||
let InOperandList = (ins);
|
||||
let Inst{25-21} = Ra;
|
||||
let Inst{20-16} = 0;
|
||||
let Inst{15-0} = fc;
|
||||
}
|
||||
class MfcPForm<bits<6> opcode, bits<16> fc, string asmstr, InstrItinClass itin>
|
||||
: InstAlpha<opcode, asmstr, itin> {
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins);
|
||||
let Inst{25-21} = 0;
|
||||
let Inst{20-16} = 0;
|
||||
let Inst{15-0} = fc;
|
||||
@ -77,7 +77,7 @@ class MbrForm<bits<6> opcode, bits<2> TB, dag OL, string asmstr, InstrItinClass
|
||||
bits<5> Rb;
|
||||
bits<14> disp;
|
||||
|
||||
let OutOperandList = (ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = OL;
|
||||
|
||||
let Inst{25-21} = Ra;
|
||||
@ -92,7 +92,7 @@ class MbrpForm<bits<6> opcode, bits<2> TB, dag OL, string asmstr, list<dag> patt
|
||||
bits<5> Rb;
|
||||
bits<14> disp;
|
||||
|
||||
let OutOperandList = (ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = OL;
|
||||
|
||||
let Inst{25-21} = Ra;
|
||||
@ -107,7 +107,7 @@ def target : Operand<OtherVT> {}
|
||||
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in {
|
||||
class BFormN<bits<6> opcode, dag OL, string asmstr, InstrItinClass itin>
|
||||
: InstAlpha<opcode, asmstr, itin> {
|
||||
let OutOperandList = (ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = OL;
|
||||
bits<64> Opc; //dummy
|
||||
bits<5> Ra;
|
||||
@ -122,8 +122,8 @@ let isBranch = 1, isTerminator = 1 in
|
||||
class BFormD<bits<6> opcode, string asmstr, list<dag> pattern, InstrItinClass itin>
|
||||
: InstAlpha<opcode, asmstr, itin> {
|
||||
let Pattern = pattern;
|
||||
let OutOperandList = (ops);
|
||||
let InOperandList = (ops target:$DISP);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = (ins target:$DISP);
|
||||
bits<5> Ra;
|
||||
bits<21> disp;
|
||||
|
||||
@ -250,7 +250,7 @@ class FPForm<bits<6> opcode, bits<11> fun, string asmstr, list<dag> pattern, Ins
|
||||
//3.3.5
|
||||
class PALForm<bits<6> opcode, dag OL, string asmstr, InstrItinClass itin>
|
||||
: InstAlpha<opcode, asmstr, itin> {
|
||||
let OutOperandList = (ops);
|
||||
let OutOperandList = (outs);
|
||||
let InOperandList = OL;
|
||||
bits<26> Function;
|
||||
|
||||
|
@ -392,12 +392,12 @@ def : Pat<(setune GPRC:$X, immUExt8:$Y), (CMPEQi (CMPEQ GPRC:$X, immUExt8:$Y), 0
|
||||
|
||||
|
||||
let isReturn = 1, isTerminator = 1, isBarrier = 1, Ra = 31, Rb = 26, disp = 1, Uses = [R26] in {
|
||||
def RETDAG : MbrForm< 0x1A, 0x02, (ops), "ret $$31,($$26),1", s_jsr>; //Return from subroutine
|
||||
def RETDAGp : MbrpForm< 0x1A, 0x02, (ops), "ret $$31,($$26),1", [(retflag)], s_jsr>; //Return from subroutine
|
||||
def RETDAG : MbrForm< 0x1A, 0x02, (ins), "ret $$31,($$26),1", s_jsr>; //Return from subroutine
|
||||
def RETDAGp : MbrpForm< 0x1A, 0x02, (ins), "ret $$31,($$26),1", [(retflag)], s_jsr>; //Return from subroutine
|
||||
}
|
||||
|
||||
let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1, Ra = 31, disp = 0 in
|
||||
def JMP : MbrpForm< 0x1A, 0x00, (ops GPRC:$RS), "jmp $$31,($RS),0",
|
||||
def JMP : MbrpForm< 0x1A, 0x00, (ins GPRC:$RS), "jmp $$31,($RS),0",
|
||||
[(brind GPRC:$RS)], s_jsr>; //Jump
|
||||
|
||||
let isCall = 1, Ra = 26,
|
||||
@ -414,18 +414,18 @@ let isCall = 1, Ra = 26, Rb = 27, disp = 0,
|
||||
F0, F1,
|
||||
F10, F11, F12, F13, F14, F15, F16, F17, F18, F19,
|
||||
F20, F21, F22, F23, F24, F25, F26, F27, F28, F29, F30], Uses = [R27, R29] in {
|
||||
def JSR : MbrForm< 0x1A, 0x01, (ops ), "jsr $$26,($$27),0", s_jsr>; //Jump to subroutine
|
||||
def JSR : MbrForm< 0x1A, 0x01, (ins), "jsr $$26,($$27),0", s_jsr>; //Jump to subroutine
|
||||
}
|
||||
|
||||
let isCall = 1, Ra = 23, Rb = 27, disp = 0,
|
||||
Defs = [R23, R24, R25, R27, R28], Uses = [R24, R25, R27] in
|
||||
def JSRs : MbrForm< 0x1A, 0x01, (ops ), "jsr $$23,($$27),0", s_jsr>; //Jump to div or rem
|
||||
def JSRs : MbrForm< 0x1A, 0x01, (ins), "jsr $$23,($$27),0", s_jsr>; //Jump to div or rem
|
||||
|
||||
|
||||
def JSR_COROUTINE : MbrForm< 0x1A, 0x03, (ops GPRC:$RD, GPRC:$RS, s14imm:$DISP), "jsr_coroutine $RD,($RS),$DISP", s_jsr>; //Jump to subroutine return
|
||||
def JSR_COROUTINE : MbrForm< 0x1A, 0x03, (ins GPRC:$RD, GPRC:$RS, s14imm:$DISP), "jsr_coroutine $RD,($RS),$DISP", s_jsr>; //Jump to subroutine return
|
||||
|
||||
|
||||
let OutOperandList = (ops GPRC:$RA), InOperandList = (ops s64imm:$DISP, GPRC:$RB) in {
|
||||
let OutOperandList = (outs GPRC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in {
|
||||
def LDQ : MForm<0x29, 1, "ldq $RA,$DISP($RB)",
|
||||
[(set GPRC:$RA, (load (add GPRC:$RB, immSExt16:$DISP)))], s_ild>;
|
||||
def LDQr : MForm<0x29, 1, "ldq $RA,$DISP($RB)\t\t!gprellow",
|
||||
@ -445,7 +445,7 @@ def LDWUr : MForm<0x0C, 1, "ldwu $RA,$DISP($RB)\t\t!gprellow",
|
||||
}
|
||||
|
||||
|
||||
let OutOperandList = (ops), InOperandList = (ops GPRC:$RA, s64imm:$DISP, GPRC:$RB) in {
|
||||
let OutOperandList = (outs), InOperandList = (ins GPRC:$RA, s64imm:$DISP, GPRC:$RB) in {
|
||||
def STB : MForm<0x0E, 0, "stb $RA,$DISP($RB)",
|
||||
[(truncstorei8 GPRC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_ist>;
|
||||
def STBr : MForm<0x0E, 0, "stb $RA,$DISP($RB)\t\t!gprellow",
|
||||
@ -465,7 +465,7 @@ def STQr : MForm<0x2D, 0, "stq $RA,$DISP($RB)\t\t!gprellow",
|
||||
}
|
||||
|
||||
//Load address
|
||||
let OutOperandList = (ops GPRC:$RA), InOperandList = (ops s64imm:$DISP, GPRC:$RB) in {
|
||||
let OutOperandList = (outs GPRC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in {
|
||||
def LDA : MForm<0x08, 0, "lda $RA,$DISP($RB)",
|
||||
[(set GPRC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_lda>;
|
||||
def LDAr : MForm<0x08, 0, "lda $RA,$DISP($RB)\t\t!gprellow",
|
||||
@ -476,25 +476,25 @@ def LDAHr : MForm<0x09, 0, "ldah $RA,$DISP($RB)\t\t!gprelhigh",
|
||||
[(set GPRC:$RA, (Alpha_gprelhi tglobaladdr:$DISP, GPRC:$RB))], s_lda>; //Load address high
|
||||
}
|
||||
|
||||
let OutOperandList = (ops), InOperandList = (ops F4RC:$RA, s64imm:$DISP, GPRC:$RB) in {
|
||||
let OutOperandList = (outs), InOperandList = (ins F4RC:$RA, s64imm:$DISP, GPRC:$RB) in {
|
||||
def STS : MForm<0x26, 0, "sts $RA,$DISP($RB)",
|
||||
[(store F4RC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_fst>;
|
||||
def STSr : MForm<0x26, 0, "sts $RA,$DISP($RB)\t\t!gprellow",
|
||||
[(store F4RC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_fst>;
|
||||
}
|
||||
let OutOperandList = (ops F4RC:$RA), InOperandList = (ops s64imm:$DISP, GPRC:$RB) in {
|
||||
let OutOperandList = (outs F4RC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in {
|
||||
def LDS : MForm<0x22, 1, "lds $RA,$DISP($RB)",
|
||||
[(set F4RC:$RA, (load (add GPRC:$RB, immSExt16:$DISP)))], s_fld>;
|
||||
def LDSr : MForm<0x22, 1, "lds $RA,$DISP($RB)\t\t!gprellow",
|
||||
[(set F4RC:$RA, (load (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB)))], s_fld>;
|
||||
}
|
||||
let OutOperandList = (ops), InOperandList = (ops F8RC:$RA, s64imm:$DISP, GPRC:$RB) in {
|
||||
let OutOperandList = (outs), InOperandList = (ins F8RC:$RA, s64imm:$DISP, GPRC:$RB) in {
|
||||
def STT : MForm<0x27, 0, "stt $RA,$DISP($RB)",
|
||||
[(store F8RC:$RA, (add GPRC:$RB, immSExt16:$DISP))], s_fst>;
|
||||
def STTr : MForm<0x27, 0, "stt $RA,$DISP($RB)\t\t!gprellow",
|
||||
[(store F8RC:$RA, (Alpha_gprello tglobaladdr:$DISP, GPRC:$RB))], s_fst>;
|
||||
}
|
||||
let OutOperandList = (ops F8RC:$RA), InOperandList = (ops s64imm:$DISP, GPRC:$RB) in {
|
||||
let OutOperandList = (outs F8RC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in {
|
||||
def LDT : MForm<0x23, 1, "ldt $RA,$DISP($RB)",
|
||||
[(set F8RC:$RA, (load (add GPRC:$RB, immSExt16:$DISP)))], s_fld>;
|
||||
def LDTr : MForm<0x23, 1, "ldt $RA,$DISP($RB)\t\t!gprellow",
|
||||
@ -570,15 +570,15 @@ def : Pat<(truncstorei8 GPRC:$DATA, GPRC:$addr),
|
||||
|
||||
|
||||
//load address, rellocated gpdist form
|
||||
let OutOperandList = (ops GPRC:$RA),
|
||||
InOperandList = (ops s16imm:$DISP, GPRC:$RB, s16imm:$NUM),
|
||||
let OutOperandList = (outs GPRC:$RA),
|
||||
InOperandList = (ins s16imm:$DISP, GPRC:$RB, s16imm:$NUM),
|
||||
mayLoad = 1 in {
|
||||
def LDAg : MForm<0x08, 1, "lda $RA,0($RB)\t\t!gpdisp!$NUM", [], s_lda>; //Load address
|
||||
def LDAHg : MForm<0x09, 1, "ldah $RA,0($RB)\t\t!gpdisp!$NUM", [], s_lda>; //Load address
|
||||
}
|
||||
|
||||
//Load quad, rellocated literal form
|
||||
let OutOperandList = (ops GPRC:$RA), InOperandList = (ops s64imm:$DISP, GPRC:$RB) in
|
||||
let OutOperandList = (outs GPRC:$RA), InOperandList = (ins s64imm:$DISP, GPRC:$RB) in
|
||||
def LDQl : MForm<0x29, 1, "ldq $RA,$DISP($RB)\t\t!literal",
|
||||
[(set GPRC:$RA, (Alpha_rellit tglobaladdr:$DISP, GPRC:$RB))], s_ild>;
|
||||
def : Pat<(Alpha_rellit texternalsym:$ext, GPRC:$RB),
|
||||
@ -591,8 +591,8 @@ let OutOperandList = (outs GPRC:$RR),
|
||||
def STQ_C : MForm<0x2F, 0, "stq_l $RA,$DISP($RB)", [], s_ist>;
|
||||
def STL_C : MForm<0x2E, 0, "stl_l $RA,$DISP($RB)", [], s_ist>;
|
||||
}
|
||||
let OutOperandList = (ops GPRC:$RA),
|
||||
InOperandList = (ops s64imm:$DISP, GPRC:$RB),
|
||||
let OutOperandList = (outs GPRC:$RA),
|
||||
InOperandList = (ins s64imm:$DISP, GPRC:$RB),
|
||||
mayLoad = 1 in {
|
||||
def LDQ_L : MForm<0x2B, 1, "ldq_l $RA,$DISP($RB)", [], s_ild>;
|
||||
def LDL_L : MForm<0x2A, 1, "ldl_l $RA,$DISP($RB)", [], s_ild>;
|
||||
@ -611,11 +611,11 @@ def : Pat<(membarrier (i64 imm), (i64 imm), (i64 imm), (i64 imm), (i64 imm)),
|
||||
|
||||
//Floats
|
||||
|
||||
let OutOperandList = (ops F4RC:$RC), InOperandList = (ops F4RC:$RB), Fa = 31 in
|
||||
let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F4RC:$RB), Fa = 31 in
|
||||
def SQRTS : FPForm<0x14, 0x58B, "sqrts/su $RB,$RC",
|
||||
[(set F4RC:$RC, (fsqrt F4RC:$RB))], s_fsqrts>;
|
||||
|
||||
let OutOperandList = (ops F4RC:$RC), InOperandList = (ops F4RC:$RA, F4RC:$RB) in {
|
||||
let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F4RC:$RA, F4RC:$RB) in {
|
||||
def ADDS : FPForm<0x16, 0x580, "adds/su $RA,$RB,$RC",
|
||||
[(set F4RC:$RC, (fadd F4RC:$RA, F4RC:$RB))], s_fadd>;
|
||||
def SUBS : FPForm<0x16, 0x581, "subs/su $RA,$RB,$RC",
|
||||
@ -634,11 +634,11 @@ def CPYSNS : FPForm<0x17, 0x021, "cpysn $RA,$RB,$RC",
|
||||
|
||||
//Doubles
|
||||
|
||||
let OutOperandList = (ops F8RC:$RC), InOperandList = (ops F8RC:$RB), Fa = 31 in
|
||||
let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in
|
||||
def SQRTT : FPForm<0x14, 0x5AB, "sqrtt/su $RB,$RC",
|
||||
[(set F8RC:$RC, (fsqrt F8RC:$RB))], s_fsqrtt>;
|
||||
|
||||
let OutOperandList = (ops F8RC:$RC), InOperandList = (ops F8RC:$RA, F8RC:$RB) in {
|
||||
let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F8RC:$RA, F8RC:$RB) in {
|
||||
def ADDT : FPForm<0x16, 0x5A0, "addt/su $RA,$RB,$RC",
|
||||
[(set F8RC:$RC, (fadd F8RC:$RA, F8RC:$RB))], s_fadd>;
|
||||
def SUBT : FPForm<0x16, 0x5A1, "subt/su $RA,$RB,$RC",
|
||||
@ -665,13 +665,13 @@ def CMPTUN : FPForm<0x16, 0x5A4, "cmptun/su $RA,$RB,$RC", [], s_fadd>;
|
||||
}
|
||||
|
||||
//More CPYS forms:
|
||||
let OutOperandList = (ops F8RC:$RC), InOperandList = (ops F4RC:$RA, F8RC:$RB) in {
|
||||
let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F4RC:$RA, F8RC:$RB) in {
|
||||
def CPYSTs : FPForm<0x17, 0x020, "cpys $RA,$RB,$RC",
|
||||
[(set F8RC:$RC, (fcopysign F8RC:$RB, F4RC:$RA))], s_fadd>;
|
||||
def CPYSNTs : FPForm<0x17, 0x021, "cpysn $RA,$RB,$RC",
|
||||
[(set F8RC:$RC, (fneg (fcopysign F8RC:$RB, F4RC:$RA)))], s_fadd>;
|
||||
}
|
||||
let OutOperandList = (ops F4RC:$RC), InOperandList = (ops F8RC:$RA, F4RC:$RB) in {
|
||||
let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F8RC:$RA, F4RC:$RB) in {
|
||||
def CPYSSt : FPForm<0x17, 0x020, "cpys $RA,$RB,$RC",
|
||||
[(set F4RC:$RC, (fcopysign F4RC:$RB, F8RC:$RA))], s_fadd>;
|
||||
def CPYSESt : FPForm<0x17, 0x022, "cpyse $RA,$RB,$RC",[], s_fadd>; //Copy sign and exponent
|
||||
@ -680,7 +680,7 @@ def CPYSNSt : FPForm<0x17, 0x021, "cpysn $RA,$RB,$RC",
|
||||
}
|
||||
|
||||
//conditional moves, floats
|
||||
let OutOperandList = (ops F4RC:$RDEST), InOperandList = (ops F4RC:$RFALSE, F4RC:$RTRUE, F8RC:$RCOND),
|
||||
let OutOperandList = (outs F4RC:$RDEST), InOperandList = (ins F4RC:$RFALSE, F4RC:$RTRUE, F8RC:$RCOND),
|
||||
isTwoAddress = 1 in {
|
||||
def FCMOVEQS : FPForm<0x17, 0x02A, "fcmoveq $RCOND,$RTRUE,$RDEST",[], s_fcmov>; //FCMOVE if = zero
|
||||
def FCMOVGES : FPForm<0x17, 0x02D, "fcmovge $RCOND,$RTRUE,$RDEST",[], s_fcmov>; //FCMOVE if >= zero
|
||||
@ -690,7 +690,7 @@ def FCMOVLTS : FPForm<0x17, 0x02C, "fcmovlt $RCOND,$RTRUE,$RDEST",[], s_fcmov>;
|
||||
def FCMOVNES : FPForm<0x17, 0x02B, "fcmovne $RCOND,$RTRUE,$RDEST",[], s_fcmov>; //FCMOVE if != zero
|
||||
}
|
||||
//conditional moves, doubles
|
||||
let OutOperandList = (ops F8RC:$RDEST), InOperandList = (ops F8RC:$RFALSE, F8RC:$RTRUE, F8RC:$RCOND),
|
||||
let OutOperandList = (outs F8RC:$RDEST), InOperandList = (ins F8RC:$RFALSE, F8RC:$RTRUE, F8RC:$RCOND),
|
||||
isTwoAddress = 1 in {
|
||||
def FCMOVEQT : FPForm<0x17, 0x02A, "fcmoveq $RCOND,$RTRUE,$RDEST", [], s_fcmov>;
|
||||
def FCMOVGET : FPForm<0x17, 0x02D, "fcmovge $RCOND,$RTRUE,$RDEST", [], s_fcmov>;
|
||||
@ -790,33 +790,33 @@ def : Pat<(select (setule F8RC:$RA, F8RC:$RB), F4RC:$st, F4RC:$sf),
|
||||
|
||||
|
||||
|
||||
let OutOperandList = (ops GPRC:$RC), InOperandList = (ops F4RC:$RA), Fb = 31 in
|
||||
let OutOperandList = (outs GPRC:$RC), InOperandList = (ins F4RC:$RA), Fb = 31 in
|
||||
def FTOIS : FPForm<0x1C, 0x078, "ftois $RA,$RC",
|
||||
[(set GPRC:$RC, (bitconvert F4RC:$RA))], s_ftoi>; //Floating to integer move, S_floating
|
||||
let OutOperandList = (ops GPRC:$RC), InOperandList = (ops F8RC:$RA), Fb = 31 in
|
||||
let OutOperandList = (outs GPRC:$RC), InOperandList = (ins F8RC:$RA), Fb = 31 in
|
||||
def FTOIT : FPForm<0x1C, 0x070, "ftoit $RA,$RC",
|
||||
[(set GPRC:$RC, (bitconvert F8RC:$RA))], s_ftoi>; //Floating to integer move
|
||||
let OutOperandList = (ops F4RC:$RC), InOperandList = (ops GPRC:$RA), Fb = 31 in
|
||||
let OutOperandList = (outs F4RC:$RC), InOperandList = (ins GPRC:$RA), Fb = 31 in
|
||||
def ITOFS : FPForm<0x14, 0x004, "itofs $RA,$RC",
|
||||
[(set F4RC:$RC, (bitconvert GPRC:$RA))], s_itof>; //Integer to floating move, S_floating
|
||||
let OutOperandList = (ops F8RC:$RC), InOperandList = (ops GPRC:$RA), Fb = 31 in
|
||||
let OutOperandList = (outs F8RC:$RC), InOperandList = (ins GPRC:$RA), Fb = 31 in
|
||||
def ITOFT : FPForm<0x14, 0x024, "itoft $RA,$RC",
|
||||
[(set F8RC:$RC, (bitconvert GPRC:$RA))], s_itof>; //Integer to floating move
|
||||
|
||||
|
||||
let OutOperandList = (ops F4RC:$RC), InOperandList = (ops F8RC:$RB), Fa = 31 in
|
||||
let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in
|
||||
def CVTQS : FPForm<0x16, 0x7BC, "cvtqs/sui $RB,$RC",
|
||||
[(set F4RC:$RC, (Alpha_cvtqs F8RC:$RB))], s_fadd>;
|
||||
let OutOperandList = (ops F8RC:$RC), InOperandList = (ops F8RC:$RB), Fa = 31 in
|
||||
let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in
|
||||
def CVTQT : FPForm<0x16, 0x7BE, "cvtqt/sui $RB,$RC",
|
||||
[(set F8RC:$RC, (Alpha_cvtqt F8RC:$RB))], s_fadd>;
|
||||
let OutOperandList = (ops F8RC:$RC), InOperandList = (ops F8RC:$RB), Fa = 31 in
|
||||
let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in
|
||||
def CVTTQ : FPForm<0x16, 0x52F, "cvttq/svc $RB,$RC",
|
||||
[(set F8RC:$RC, (Alpha_cvttq F8RC:$RB))], s_fadd>;
|
||||
let OutOperandList = (ops F8RC:$RC), InOperandList = (ops F4RC:$RB), Fa = 31 in
|
||||
let OutOperandList = (outs F8RC:$RC), InOperandList = (ins F4RC:$RB), Fa = 31 in
|
||||
def CVTST : FPForm<0x16, 0x6AC, "cvtst/s $RB,$RC",
|
||||
[(set F8RC:$RC, (fextend F4RC:$RB))], s_fadd>;
|
||||
let OutOperandList = (ops F4RC:$RC), InOperandList = (ops F8RC:$RB), Fa = 31 in
|
||||
let OutOperandList = (outs F4RC:$RC), InOperandList = (ins F8RC:$RB), Fa = 31 in
|
||||
def CVTTS : FPForm<0x16, 0x7AC, "cvtts/sui $RB,$RC",
|
||||
[(set F4RC:$RC, (fround F8RC:$RB))], s_fadd>;
|
||||
|
||||
@ -829,20 +829,20 @@ def : Pat<(select GPRC:$RC, F4RC:$st, F4RC:$sf),
|
||||
//Branching
|
||||
/////////////////////////////////////////////////////////
|
||||
class br_icc<bits<6> opc, string asmstr>
|
||||
: BFormN<opc, (ops u64imm:$opc, GPRC:$R, target:$dst),
|
||||
: BFormN<opc, (ins u64imm:$opc, GPRC:$R, target:$dst),
|
||||
!strconcat(asmstr, " $R,$dst"), s_icbr>;
|
||||
class br_fcc<bits<6> opc, string asmstr>
|
||||
: BFormN<opc, (ops u64imm:$opc, F8RC:$R, target:$dst),
|
||||
: BFormN<opc, (ins u64imm:$opc, F8RC:$R, target:$dst),
|
||||
!strconcat(asmstr, " $R,$dst"), s_fbr>;
|
||||
|
||||
let isBranch = 1, isTerminator = 1, hasCtrlDep = 1 in {
|
||||
let Ra = 31 in
|
||||
def BR : BFormD<0x30, "br $$31,$DISP", [(br bb:$DISP)], s_ubr>;
|
||||
|
||||
def COND_BRANCH_I : BFormN<0, (ops u64imm:$opc, GPRC:$R, target:$dst),
|
||||
def COND_BRANCH_I : BFormN<0, (ins u64imm:$opc, GPRC:$R, target:$dst),
|
||||
"{:comment} COND_BRANCH imm:$opc, GPRC:$R, bb:$dst",
|
||||
s_icbr>;
|
||||
def COND_BRANCH_F : BFormN<0, (ops u64imm:$opc, F8RC:$R, target:$dst),
|
||||
def COND_BRANCH_F : BFormN<0, (ins u64imm:$opc, F8RC:$R, target:$dst),
|
||||
"{:comment} COND_BRANCH imm:$opc, F8RC:$R, bb:$dst",
|
||||
s_fbr>;
|
||||
//Branches, int
|
||||
|
@ -29,7 +29,8 @@ def BfinCallseqEnd : SDNode<"ISD::CALLSEQ_END", SDT_BfinCallSeqEnd,
|
||||
|
||||
def SDT_BfinCall : SDTypeProfile<0, 1, [SDTCisPtrTy<0>]>;
|
||||
def BfinCall : SDNode<"BFISD::CALL", SDT_BfinCall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
|
||||
def BfinRet: SDNode<"BFISD::RET_FLAG", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
@ -610,7 +611,7 @@ def MOVE_ncccc : F1<(outs NotCC:$cc), (ins JustCC:$sb),
|
||||
|
||||
def MOVECC_zext : F1<(outs D:$dst), (ins JustCC:$cc),
|
||||
"$dst = $cc;",
|
||||
[(set D:$dst, (zext JustCC:$cc))]>;
|
||||
[/*(set D:$dst, (zext JustCC:$cc))*/]>;
|
||||
|
||||
def MOVENCC_z : F1<(outs D:$dst), (ins NotCC:$cc),
|
||||
"$dst = cc;", []>;
|
||||
@ -859,10 +860,10 @@ def : Pat<(BfinCall (i32 tglobaladdr:$dst)),
|
||||
def : Pat<(BfinCall (i32 texternalsym:$dst)),
|
||||
(CALLa texternalsym:$dst)>;
|
||||
|
||||
def : Pat<(sext JustCC:$cc),
|
||||
(NEG (MOVECC_zext JustCC:$cc))>;
|
||||
def : Pat<(anyext JustCC:$cc),
|
||||
(MOVECC_zext JustCC:$cc)>;
|
||||
//def : Pat<(sext JustCC:$cc),
|
||||
// (NEG (MOVECC_zext JustCC:$cc))>;
|
||||
//def : Pat<(anyext JustCC:$cc),
|
||||
// (MOVECC_zext JustCC:$cc)>;
|
||||
def : Pat<(i16 (zext JustCC:$cc)),
|
||||
(EXTRACT_SUBREG (MOVECC_zext JustCC:$cc), bfin_subreg_lo16)>;
|
||||
def : Pat<(i16 (sext JustCC:$cc)),
|
||||
|
@ -53,6 +53,10 @@ std::string BlackfinIntrinsicInfo::getName(unsigned IntrID, const Type **Tys,
|
||||
|
||||
unsigned
|
||||
BlackfinIntrinsicInfo::lookupName(const char *Name, unsigned Len) const {
|
||||
if (Len < 5 || Name[4] != '.' || Name[0] != 'l' || Name[1] != 'l'
|
||||
|| Name[2] != 'v' || Name[3] != 'm')
|
||||
return 0; // All intrinsics start with 'llvm.'
|
||||
|
||||
#define GET_FUNCTION_RECOGNIZER
|
||||
#include "BlackfinGenIntrinsics.inc"
|
||||
#undef GET_FUNCTION_RECOGNIZER
|
||||
|
@ -111,7 +111,8 @@ namespace {
|
||||
static char ID;
|
||||
explicit CWriter(formatted_raw_ostream &o)
|
||||
: FunctionPass(&ID), Out(o), IL(0), Mang(0), LI(0),
|
||||
TheModule(0), TAsm(0), TD(0), OpaqueCounter(0), NextAnonValueNumber(0) {
|
||||
TheModule(0), TAsm(0), TCtx(0), TD(0), OpaqueCounter(0),
|
||||
NextAnonValueNumber(0) {
|
||||
FPCounter = 0;
|
||||
}
|
||||
|
||||
@ -147,6 +148,8 @@ namespace {
|
||||
delete IL;
|
||||
delete TD;
|
||||
delete Mang;
|
||||
delete TCtx;
|
||||
delete TAsm;
|
||||
FPConstantMap.clear();
|
||||
TypeNames.clear();
|
||||
ByValParams.clear();
|
||||
|
@ -1133,16 +1133,14 @@ class XSBHInst<dag OOL, dag IOL, list<dag> pattern>:
|
||||
"xsbh\t$rDst, $rSrc",
|
||||
IntegerOp, pattern>;
|
||||
|
||||
class XSBHVecInst<ValueType vectype>:
|
||||
XSBHInst<(outs VECREG:$rDst), (ins VECREG:$rSrc),
|
||||
[(set (v8i16 VECREG:$rDst), (sext (vectype VECREG:$rSrc)))]>;
|
||||
|
||||
class XSBHInRegInst<RegisterClass rclass, list<dag> pattern>:
|
||||
XSBHInst<(outs rclass:$rDst), (ins rclass:$rSrc),
|
||||
pattern>;
|
||||
|
||||
multiclass ExtendByteHalfword {
|
||||
def v16i8: XSBHVecInst<v8i16>;
|
||||
def v16i8: XSBHInst<(outs VECREG:$rDst), (ins VECREG:$rSrc),
|
||||
[
|
||||
/*(set (v8i16 VECREG:$rDst), (sext (v8i16 VECREG:$rSrc)))*/]>;
|
||||
def r8: XSBHInst<(outs R16C:$rDst), (ins R8C:$rSrc),
|
||||
[(set R16C:$rDst, (sext R8C:$rSrc))]>;
|
||||
def r16: XSBHInRegInst<R16C,
|
||||
@ -1200,8 +1198,8 @@ class XSWDInst<dag OOL, dag IOL, list<dag> pattern>:
|
||||
|
||||
class XSWDVecInst<ValueType in_vectype, ValueType out_vectype>:
|
||||
XSWDInst<(outs VECREG:$rDst), (ins VECREG:$rSrc),
|
||||
[(set (out_vectype VECREG:$rDst),
|
||||
(sext (out_vectype VECREG:$rSrc)))]>;
|
||||
[/*(set (out_vectype VECREG:$rDst),
|
||||
(sext (out_vectype VECREG:$rSrc)))*/]>;
|
||||
|
||||
class XSWDRegInst<RegisterClass in_rclass, RegisterClass out_rclass>:
|
||||
XSWDInst<(outs out_rclass:$rDst), (ins in_rclass:$rSrc),
|
||||
@ -4146,7 +4144,7 @@ def CFSif32 :
|
||||
def FESDvec :
|
||||
RRForm_1<0b00011101110, (outs VECREG:$rT), (ins VECREG:$rA),
|
||||
"fesd\t$rT, $rA", SPrecFP,
|
||||
[(set (v2f64 VECREG:$rT), (fextend (v4f32 VECREG:$rA)))]>;
|
||||
[/*(set (v2f64 VECREG:$rT), (fextend (v4f32 VECREG:$rA)))*/]>;
|
||||
|
||||
def FESDf32 :
|
||||
RRForm_1<0b00011101110, (outs R64FP:$rT), (ins R32FP:$rA),
|
||||
|
@ -28,7 +28,8 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_SPUCallSeq,
|
||||
|
||||
def SDT_SPUCall : SDTypeProfile<0, -1, [SDTCisPtrTy<0>]>;
|
||||
def SPUcall : SDNode<"SPUISD::CALL", SDT_SPUCall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
|
||||
// Operand type constraints for vector shuffle/permute operations
|
||||
def SDT_SPUshuffle : SDTypeProfile<1, 3, [
|
||||
|
@ -57,6 +57,10 @@ std::string MBlazeIntrinsicInfo::getName(unsigned IntrID, const Type **Tys,
|
||||
|
||||
unsigned MBlazeIntrinsicInfo::
|
||||
lookupName(const char *Name, unsigned Len) const {
|
||||
if (Len < 5 || Name[4] != '.' || Name[0] != 'l' || Name[1] != 'l'
|
||||
|| Name[2] != 'v' || Name[3] != 'm')
|
||||
return 0; // All intrinsics start with 'llvm.'
|
||||
|
||||
#define GET_FUNCTION_RECOGNIZER
|
||||
#include "MBlazeGenIntrinsics.inc"
|
||||
#undef GET_FUNCTION_RECOGNIZER
|
||||
|
@ -29,7 +29,8 @@ def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
|
||||
|
||||
// Call
|
||||
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink,
|
||||
[SDNPHasChain, SDNPOutFlag, SDNPOptInFlag]>;
|
||||
[SDNPHasChain, SDNPOutFlag, SDNPOptInFlag,
|
||||
SDNPVariadic]>;
|
||||
|
||||
// Hi and Lo nodes are used to handle global addresses. Used on
|
||||
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
|
||||
|
@ -184,7 +184,7 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
|
||||
// by any chance, as we do not link in those as .bc lib. So these calls
|
||||
// are always external and it is safe to emit an extern.
|
||||
if (PAN::isMemIntrinsic(Sym->getName()))
|
||||
LibcallDecls.push_back(createESName(Sym->getName()));
|
||||
LibcallDecls.insert(Sym->getName());
|
||||
|
||||
O << *Sym;
|
||||
break;
|
||||
@ -199,7 +199,7 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
|
||||
Printname = PAN::Rename(Sname);
|
||||
}
|
||||
// Record these decls, we need to print them in asm as extern.
|
||||
LibcallDecls.push_back(createESName(Printname));
|
||||
LibcallDecls.insert(Printname);
|
||||
}
|
||||
|
||||
O << Printname;
|
||||
@ -221,18 +221,6 @@ void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
|
||||
O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
|
||||
}
|
||||
|
||||
// This function is used to sort the decls list.
|
||||
// should return true if s1 should come before s2.
|
||||
static bool is_before(const char *s1, const char *s2) {
|
||||
return strcmp(s1, s2) <= 0;
|
||||
}
|
||||
|
||||
// This is used by list::unique below.
|
||||
// unique will filter out duplicates if it knows them.
|
||||
static bool is_duplicate(const char *s1, const char *s2) {
|
||||
return !strcmp(s1, s2);
|
||||
}
|
||||
|
||||
/// printLibcallDecls - print the extern declarations for compiler
|
||||
/// intrinsics.
|
||||
///
|
||||
@ -241,12 +229,9 @@ void PIC16AsmPrinter::printLibcallDecls() {
|
||||
if (LibcallDecls.empty()) return;
|
||||
|
||||
O << MAI->getCommentString() << "External decls for libcalls - BEGIN." <<"\n";
|
||||
// Remove duplicate entries.
|
||||
LibcallDecls.sort(is_before);
|
||||
LibcallDecls.unique(is_duplicate);
|
||||
|
||||
for (std::list<const char*>::const_iterator I = LibcallDecls.begin();
|
||||
I != LibcallDecls.end(); I++) {
|
||||
for (std::set<std::string>::const_iterator I = LibcallDecls.begin(),
|
||||
E = LibcallDecls.end(); I != E; I++) {
|
||||
O << MAI->getExternDirective() << *I << "\n";
|
||||
}
|
||||
O << MAI->getCommentString() << "External decls for libcalls - END." <<"\n";
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
@ -80,7 +81,7 @@ namespace llvm {
|
||||
PIC16TargetLowering *PTLI;
|
||||
PIC16DbgInfo DbgInfo;
|
||||
const PIC16MCAsmInfo *PMAI;
|
||||
std::list<const char *> LibcallDecls; // List of extern decls.
|
||||
std::set<std::string> LibcallDecls; // Sorted & uniqued set of extern decls.
|
||||
std::vector<const GlobalVariable *> ExternalVarDecls;
|
||||
std::vector<const GlobalVariable *> ExternalVarDefs;
|
||||
};
|
||||
|
@ -45,7 +45,7 @@ namespace llvm {
|
||||
|
||||
PIC16Section(const StringRef &name, SectionKind K, const std::string &addr,
|
||||
int color)
|
||||
: MCSection(K), Name(name), Address(addr), Color(color) {
|
||||
: MCSection(K), Name(name), Address(addr), Color(color), Size(0) {
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -111,9 +111,11 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_PPCCallSeqEnd,
|
||||
|
||||
def SDT_PPCCall : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
|
||||
def PPCcall_Darwin : SDNode<"PPCISD::CALL_Darwin", SDT_PPCCall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
def PPCcall_SVR4 : SDNode<"PPCISD::CALL_SVR4", SDT_PPCCall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
def PPCnop : SDNode<"PPCISD::NOP", SDT_PPCnop, [SDNPInFlag, SDNPOutFlag]>;
|
||||
def PPCload : SDNode<"PPCISD::LOAD", SDTypeProfile<1, 1, []>,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
@ -124,16 +126,18 @@ def PPCtoc_restore : SDNode<"PPCISD::TOC_RESTORE", SDTypeProfile<0, 0, []>,
|
||||
def PPCmtctr : SDNode<"PPCISD::MTCTR", SDT_PPCCall,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
def PPCbctrl_Darwin : SDNode<"PPCISD::BCTRL_Darwin", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
|
||||
def PPCbctrl_SVR4 : SDNode<"PPCISD::BCTRL_SVR4", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag,
|
||||
SDNPVariadic]>;
|
||||
|
||||
def retflag : SDNode<"PPCISD::RET_FLAG", SDTNone,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPVariadic]>;
|
||||
|
||||
def PPCtc_return : SDNode<"PPCISD::TC_RETURN", SDT_PPCTC_ret,
|
||||
[SDNPHasChain, SDNPOptInFlag]>;
|
||||
[SDNPHasChain, SDNPOptInFlag, SDNPVariadic]>;
|
||||
|
||||
def PPCvcmp : SDNode<"PPCISD::VCMP" , SDT_PPCvcmp, []>;
|
||||
def PPCvcmp_o : SDNode<"PPCISD::VCMPo", SDT_PPCvcmp, [SDNPOutFlag]>;
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "llvm/Support/FormattedStream.h"
|
||||
using namespace llvm;
|
||||
|
||||
static const MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
|
||||
static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
|
||||
Triple TheTriple(TT);
|
||||
bool isPPC64 = TheTriple.getArch() == Triple::ppc64;
|
||||
if (TheTriple.getOS() == Triple::Darwin)
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user