Update LLVM to r108243.
This commit is contained in:
parent
abdf259d48
commit
66e41e3c6e
@ -4,7 +4,7 @@ project(LLVM)
|
||||
cmake_minimum_required(VERSION 2.6.1)
|
||||
|
||||
set(PACKAGE_NAME llvm)
|
||||
set(PACKAGE_VERSION 2.7svn)
|
||||
set(PACKAGE_VERSION 2.8svn)
|
||||
set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
|
||||
set(PACKAGE_BUGREPORT "llvmbugs@cs.uiuc.edu")
|
||||
|
||||
|
6
Makefile
6
Makefile
@ -64,7 +64,7 @@ endif
|
||||
|
||||
ifeq ($(MAKECMDGOALS),install-clang)
|
||||
DIRS := tools/clang/tools/driver tools/clang/lib/Headers \
|
||||
tools/clang/lib/Runtime tools/clang/docs
|
||||
tools/clang/runtime tools/clang/docs
|
||||
OPTIONAL_DIRS :=
|
||||
NO_INSTALL = 1
|
||||
endif
|
||||
@ -180,8 +180,8 @@ $(FilesToConfigPATH) : $(LLVM_OBJ_ROOT)/% : $(LLVM_SRC_ROOT)/%.in
|
||||
# that it gets executed last.
|
||||
ifneq ($(BUILD_DIRS_ONLY),1)
|
||||
all::
|
||||
$(Echo) '*****' Completed $(BuildMode)$(AssertMode) Build
|
||||
ifeq ($(BuildMode),Debug)
|
||||
$(Echo) '*****' Completed $(BuildMode) Build
|
||||
ifneq ($(ENABLE_OPTIMIZED),1)
|
||||
$(Echo) '*****' Note: Debug build can be 10 times slower than an
|
||||
$(Echo) '*****' optimized build. Use 'make ENABLE_OPTIMIZED=1' to
|
||||
$(Echo) '*****' make an optimized build. Alternatively you can
|
||||
|
@ -222,8 +222,8 @@ RDYNAMIC := @RDYNAMIC@
|
||||
|
||||
# When ENABLE_PROFILING is enabled, profile instrumentation is done
|
||||
# and output is put into the "<Flavor>+Profile" directories, where
|
||||
# <Flavor> is either Debug or Release depending on how other builkd
|
||||
# flags are set.. Otherwise, output is put in the <Flavor>
|
||||
# <Flavor> is either Debug or Release depending on how other build
|
||||
# flags are set. Otherwise, output is put in the <Flavor>
|
||||
# directories.
|
||||
#ENABLE_PROFILING = 1
|
||||
@ENABLE_PROFILING@
|
||||
@ -320,12 +320,6 @@ endif
|
||||
# Location of the plugin header file for gold.
|
||||
BINUTILS_INCDIR := @BINUTILS_INCDIR@
|
||||
|
||||
C_INCLUDE_DIRS := @C_INCLUDE_DIRS@
|
||||
CXX_INCLUDE_ROOT := @CXX_INCLUDE_ROOT@
|
||||
CXX_INCLUDE_ARCH := @CXX_INCLUDE_ARCH@
|
||||
CXX_INCLUDE_32BIT_DIR = @CXX_INCLUDE_32BIT_DIR@
|
||||
CXX_INCLUDE_64BIT_DIR = @CXX_INCLUDE_64BIT_DIR@
|
||||
|
||||
# When ENABLE_LLVMC_DYNAMIC is enabled, LLVMC will link libCompilerDriver
|
||||
# dynamically. This is needed to make dynamic plugins work on some targets
|
||||
# (Windows).
|
||||
@ -344,5 +338,5 @@ NO_MISSING_FIELD_INITIALIZERS = @NO_MISSING_FIELD_INITIALIZERS@
|
||||
NO_VARIADIC_MACROS = @NO_VARIADIC_MACROS@
|
||||
|
||||
# Flags supported by the linker.
|
||||
# bfd ld / gold -retain-symbols-file file
|
||||
HAVE_LINK_RETAIN_SYMBOLS_FILE = @HAVE_LINK_RETAIN_SYMBOLS_FILE@
|
||||
# bfd ld / gold --version-script=file
|
||||
HAVE_LINK_VERSION_SCRIPT = @HAVE_LINK_VERSION_SCRIPT@
|
||||
|
@ -398,12 +398,11 @@ endif
|
||||
|
||||
# If DISABLE_ASSERTIONS=1 is specified (make command line or configured),
|
||||
# then disable assertions by defining the appropriate preprocessor symbols.
|
||||
ifdef DISABLE_ASSERTIONS
|
||||
# Indicate that assertions are turned off using a minus sign
|
||||
BuildMode := $(BuildMode)-Asserts
|
||||
CPP.Defines += -DNDEBUG
|
||||
else
|
||||
ifndef DISABLE_ASSERTIONS
|
||||
BuildMode := $(BuildMode)+Asserts
|
||||
CPP.Defines += -D_DEBUG
|
||||
else
|
||||
CPP.Defines += -DNDEBUG
|
||||
endif
|
||||
|
||||
# If ENABLE_EXPENSIVE_CHECKS=1 is specified (make command line or
|
||||
@ -807,7 +806,8 @@ SubDirs += $(DIRS)
|
||||
ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
|
||||
$(RecursiveTargets)::
|
||||
$(Verb) for dir in $(DIRS); do \
|
||||
if [ ! -f $$dir/Makefile ]; then \
|
||||
if ([ ! -f $$dir/Makefile ] || \
|
||||
command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \
|
||||
$(MKDIR) $$dir; \
|
||||
$(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \
|
||||
fi; \
|
||||
@ -829,7 +829,8 @@ endif
|
||||
ifdef EXPERIMENTAL_DIRS
|
||||
$(RecursiveTargets)::
|
||||
$(Verb) for dir in $(EXPERIMENTAL_DIRS); do \
|
||||
if [ ! -f $$dir/Makefile ]; then \
|
||||
if ([ ! -f $$dir/Makefile ] || \
|
||||
command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \
|
||||
$(MKDIR) $$dir; \
|
||||
$(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \
|
||||
fi; \
|
||||
@ -863,7 +864,9 @@ unitcheck:: $(addsuffix /.makeunitcheck,$(PARALLEL_DIRS))
|
||||
ParallelTargets := $(foreach T,$(RecursiveTargets),%/.make$(T))
|
||||
|
||||
$(ParallelTargets) :
|
||||
$(Verb) if [ ! -f $(@D)/Makefile ]; then \
|
||||
$(Verb) if ([ ! -f $(@D)/Makefile ] || \
|
||||
command test $(@D)/Makefile -ot \
|
||||
$(PROJ_SRC_DIR)/$(@D)/Makefile ); then \
|
||||
$(MKDIR) $(@D); \
|
||||
$(CP) $(PROJ_SRC_DIR)/$(@D)/Makefile $(@D)/Makefile; \
|
||||
fi; \
|
||||
@ -882,7 +885,8 @@ ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
|
||||
$(RecursiveTargets)::
|
||||
$(Verb) for dir in $(OPTIONAL_DIRS); do \
|
||||
if [ -d $(PROJ_SRC_DIR)/$$dir ]; then\
|
||||
if [ ! -f $$dir/Makefile ]; then \
|
||||
if ([ ! -f $$dir/Makefile ] || \
|
||||
command test $$dir/Makefile -ot $(PROJ_SRC_DIR)/$$dir/Makefile ); then \
|
||||
$(MKDIR) $$dir; \
|
||||
$(CP) $(PROJ_SRC_DIR)/$$dir/Makefile $$dir/Makefile; \
|
||||
fi; \
|
||||
@ -930,7 +934,7 @@ endif
|
||||
endif
|
||||
|
||||
###############################################################################
|
||||
# Set up variables for building libararies
|
||||
# Set up variables for building libraries
|
||||
###############################################################################
|
||||
|
||||
#---------------------------------------------------------
|
||||
@ -986,12 +990,25 @@ ifeq ($(HOST_OS),Darwin)
|
||||
# Darwin convention prefixes symbols with underscores.
|
||||
NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE)).sed
|
||||
$(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir
|
||||
$(Verb) sed -e 's/[[:<:]]/_/' < $< > $@
|
||||
$(Verb) sed -e 's/^/_/' < $< > $@
|
||||
clean-local::
|
||||
-$(Verb) $(RM) -f $(NativeExportsFile)
|
||||
else
|
||||
ifeq ($(HAVE_LINK_VERSION_SCRIPT),1)
|
||||
# Gold and BFD ld require a version script rather than a plain list.
|
||||
NativeExportsFile := $(ObjDir)/$(notdir $(EXPORTED_SYMBOL_FILE)).map
|
||||
$(NativeExportsFile): $(EXPORTED_SYMBOL_FILE) $(ObjDir)/.dir
|
||||
$(Verb) echo "{" > $@
|
||||
$(Verb) grep -q "\<" $< && echo " global:" >> $@ || :
|
||||
$(Verb) sed -e 's/$$/;/' -e 's/^/ /' < $< >> $@
|
||||
$(Verb) echo " local: *;" >> $@
|
||||
$(Verb) echo "};" >> $@
|
||||
clean-local::
|
||||
-$(Verb) $(RM) -f $(NativeExportsFile)
|
||||
else
|
||||
NativeExportsFile := $(EXPORTED_SYMBOL_FILE)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Now add the linker command-line options to use the native export file.
|
||||
|
||||
@ -1000,8 +1017,8 @@ LLVMLibsOptions += -Wl,-exported_symbols_list,$(NativeExportsFile)
|
||||
endif
|
||||
|
||||
# gold, bfd ld, etc.
|
||||
ifeq ($(HAVE_LINK_RETAIN_SYMBOLS_FILE),1)
|
||||
LLVMLibsOptions += -Wl,-retain-symbols-file,$(NativeExportsFile)
|
||||
ifeq ($(HAVE_LINK_VERSION_SCRIPT),1)
|
||||
LLVMLibsOptions += -Wl,--version-script,$(NativeExportsFile)
|
||||
endif
|
||||
|
||||
endif
|
||||
@ -1113,7 +1130,7 @@ $(LibName.SO): $(ObjectsO) $(ProjLibsPaths) $(LLVMLibsPaths) $(LibDir)/.dir
|
||||
$(ProjLibsOptions) $(LLVMLibsOptions) $(LIBS)
|
||||
else
|
||||
$(LibName.SO): $(ObjectsO) $(LibDir)/.dir
|
||||
$(Echo) Linking $(BuildMode) Shared Library $(LIBRARYNAME)$(SHLIBEXT)
|
||||
$(Echo) Linking $(BuildMode) Shared Library $(basename $@)
|
||||
$(Verb) $(Link) $(SharedLinkOptions) -o $@ $(ObjectsO)
|
||||
endif
|
||||
|
||||
|
@ -1039,8 +1039,8 @@ AC_LINK_USE_R
|
||||
dnl Determine whether the linker supports the -export-dynamic option.
|
||||
AC_LINK_EXPORT_DYNAMIC
|
||||
|
||||
dnl Determine whether the linker supports the -retain-symbols-file option.
|
||||
AC_LINK_RETAIN_SYMBOLS_FILE
|
||||
dnl Determine whether the linker supports the --version-script option.
|
||||
AC_LINK_VERSION_SCRIPT
|
||||
|
||||
dnl Check for libtool and the library that has dlopen function (which must come
|
||||
dnl before the AC_PROG_LIBTOOL check in order to enable dlopening libraries with
|
||||
@ -1284,6 +1284,9 @@ if test "$llvm_cv_enable_libffi" = "yes" ; then
|
||||
AC_CHECK_HEADERS([ffi.h ffi/ffi.h])
|
||||
fi
|
||||
|
||||
dnl Try to find Darwin specific crash reporting library.
|
||||
AC_CHECK_HEADERS([CrashReporterClient.h])
|
||||
|
||||
dnl===-----------------------------------------------------------------------===
|
||||
dnl===
|
||||
dnl=== SECTION 7: Check for types and structures
|
||||
|
@ -40,14 +40,14 @@ if test "$llvm_cv_link_use_export_dynamic" = yes ; then
|
||||
])
|
||||
|
||||
#
|
||||
# Determine if the system can handle the -retain-symbols-file option being
|
||||
# Determine if the system can handle the --version-script option being
|
||||
# passed to the linker.
|
||||
#
|
||||
# This macro is specific to LLVM.
|
||||
#
|
||||
AC_DEFUN([AC_LINK_RETAIN_SYMBOLS_FILE],
|
||||
[AC_CACHE_CHECK([for compiler -Wl,-retain-symbols-file option],
|
||||
[llvm_cv_link_use_retain_symbols_file],
|
||||
AC_DEFUN([AC_LINK_VERSION_SCRIPT],
|
||||
[AC_CACHE_CHECK([for compiler -Wl,--version-script option],
|
||||
[llvm_cv_link_use_version_script],
|
||||
[ AC_LANG_PUSH([C])
|
||||
oldcflags="$CFLAGS"
|
||||
|
||||
@ -67,18 +67,21 @@ AC_DEFUN([AC_LINK_RETAIN_SYMBOLS_FILE],
|
||||
(umask 077 && mkdir "$tmp")
|
||||
} || exit $?
|
||||
|
||||
echo "main" > "$tmp/exports"
|
||||
echo "{" > "$tmp/export.map"
|
||||
echo " global: main;" >> "$tmp/export.map"
|
||||
echo " local: *;" >> "$tmp/export.map"
|
||||
echo "};" >> "$tmp/export.map"
|
||||
|
||||
CFLAGS="$CFLAGS -Wl,-retain-symbols-file=$tmp/exports"
|
||||
CFLAGS="$CFLAGS -Wl,--version-script=$tmp/export.map"
|
||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],
|
||||
[llvm_cv_link_use_retain_symbols_file=yes],[llvm_cv_link_use_retain_symbols_file=no])
|
||||
rm "$tmp/exports"
|
||||
[llvm_cv_link_use_version_script=yes],[llvm_cv_link_use_version_script=no])
|
||||
rm "$tmp/export.map"
|
||||
rmdir "$tmp"
|
||||
CFLAGS="$oldcflags"
|
||||
AC_LANG_POP([C])
|
||||
])
|
||||
if test "$llvm_cv_link_use_retain_symbols_file" = yes ; then
|
||||
AC_SUBST(HAVE_LINK_RETAIN_SYMBOLS_FILE,1)
|
||||
if test "$llvm_cv_link_use_version_script" = yes ; then
|
||||
AC_SUBST(HAVE_LINK_VERSION_SCRIPT,1)
|
||||
fi
|
||||
])
|
||||
|
||||
|
@ -316,7 +316,8 @@ package llvm is
|
||||
LLVMExternalWeakLinkage,
|
||||
LLVMGhostLinkage,
|
||||
LLVMCommonLinkage,
|
||||
LLVMLinkerPrivateLinkage);
|
||||
LLVMLinkerPrivateLinkage,
|
||||
LLVMLinkerPrivateWeakLinkage);
|
||||
|
||||
for LLVMLinkage use
|
||||
(LLVMExternalLinkage => 0,
|
||||
@ -333,7 +334,8 @@ package llvm is
|
||||
LLVMExternalWeakLinkage => 11,
|
||||
LLVMGhostLinkage => 12,
|
||||
LLVMCommonLinkage => 13,
|
||||
LLVMLinkerPrivateLinkage => 14);
|
||||
LLVMLinkerPrivateLinkage => 14,
|
||||
LLVMLinkerPrivateWeakLinkage => 15);
|
||||
|
||||
pragma Convention (C, LLVMLinkage);
|
||||
|
||||
|
@ -4,7 +4,7 @@ include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
include(CheckCXXSourceCompiles)
|
||||
|
||||
if( UNIX )
|
||||
if( UNIX AND NOT BEOS )
|
||||
# Used by check_symbol_exists:
|
||||
set(CMAKE_REQUIRED_LIBRARIES m)
|
||||
endif()
|
||||
|
@ -6,10 +6,16 @@ macro(tablegen ofn)
|
||||
file(GLOB local_tds "*.td")
|
||||
file(GLOB_RECURSE global_tds "${LLVM_MAIN_SRC_DIR}/include/llvm/*.td")
|
||||
|
||||
if (IS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})
|
||||
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE ${LLVM_TARGET_DEFINITIONS})
|
||||
else()
|
||||
set(LLVM_TARGET_DEFINITIONS_ABSOLUTE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS})
|
||||
endif()
|
||||
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
|
||||
COMMAND ${LLVM_TABLEGEN_EXE} ${ARGN} -I ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
-I ${LLVM_MAIN_SRC_DIR}/lib/Target -I ${LLVM_MAIN_INCLUDE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/${LLVM_TARGET_DEFINITIONS}
|
||||
${LLVM_TARGET_DEFINITIONS_ABSOLUTE}
|
||||
-o ${CMAKE_CURRENT_BINARY_DIR}/${ofn}
|
||||
DEPENDS tblgen ${local_tds} ${global_tds}
|
||||
COMMENT "Building ${ofn}..."
|
||||
|
203
configure
vendored
203
configure
vendored
@ -752,7 +752,7 @@ OCAMLOPT
|
||||
OCAMLDEP
|
||||
OCAMLDOC
|
||||
GAS
|
||||
HAVE_LINK_RETAIN_SYMBOLS_FILE
|
||||
HAVE_LINK_VERSION_SCRIPT
|
||||
INSTALL_LTDL_TRUE
|
||||
INSTALL_LTDL_FALSE
|
||||
CONVENIENCE_LTDL_TRUE
|
||||
@ -8905,9 +8905,9 @@ _ACEOF
|
||||
fi
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for compiler -Wl,-retain-symbols-file option" >&5
|
||||
echo $ECHO_N "checking for compiler -Wl,-retain-symbols-file option... $ECHO_C" >&6; }
|
||||
if test "${llvm_cv_link_use_retain_symbols_file+set}" = set; then
|
||||
{ echo "$as_me:$LINENO: checking for compiler -Wl,--version-script option" >&5
|
||||
echo $ECHO_N "checking for compiler -Wl,--version-script option... $ECHO_C" >&6; }
|
||||
if test "${llvm_cv_link_use_version_script+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_ext=c
|
||||
@ -8934,9 +8934,12 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
(umask 077 && mkdir "$tmp")
|
||||
} || exit $?
|
||||
|
||||
echo "main" > "$tmp/exports"
|
||||
echo "{" > "$tmp/export.map"
|
||||
echo " global: main;" >> "$tmp/export.map"
|
||||
echo " local: *;" >> "$tmp/export.map"
|
||||
echo "};" >> "$tmp/export.map"
|
||||
|
||||
CFLAGS="$CFLAGS -Wl,-retain-symbols-file=$tmp/exports"
|
||||
CFLAGS="$CFLAGS -Wl,--version-script=$tmp/export.map"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
@ -8986,17 +8989,17 @@ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
llvm_cv_link_use_retain_symbols_file=yes
|
||||
llvm_cv_link_use_version_script=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
llvm_cv_link_use_retain_symbols_file=no
|
||||
llvm_cv_link_use_version_script=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
rm "$tmp/exports"
|
||||
rm "$tmp/export.map"
|
||||
rmdir "$tmp"
|
||||
CFLAGS="$oldcflags"
|
||||
ac_ext=c
|
||||
@ -9007,10 +9010,10 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_retain_symbols_file" >&5
|
||||
echo "${ECHO_T}$llvm_cv_link_use_retain_symbols_file" >&6; }
|
||||
if test "$llvm_cv_link_use_retain_symbols_file" = yes ; then
|
||||
HAVE_LINK_RETAIN_SYMBOLS_FILE=1
|
||||
{ echo "$as_me:$LINENO: result: $llvm_cv_link_use_version_script" >&5
|
||||
echo "${ECHO_T}$llvm_cv_link_use_version_script" >&6; }
|
||||
if test "$llvm_cv_link_use_version_script" = yes ; then
|
||||
HAVE_LINK_VERSION_SCRIPT=1
|
||||
|
||||
fi
|
||||
|
||||
@ -11384,7 +11387,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 11387 "configure"
|
||||
#line 11390 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -16947,6 +16950,176 @@ done
|
||||
fi
|
||||
|
||||
|
||||
for ac_header in CrashReporterClient.h
|
||||
do
|
||||
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
fi
|
||||
ac_res=`eval echo '${'$as_ac_Header'}'`
|
||||
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||
echo "${ECHO_T}$ac_res" >&6; }
|
||||
else
|
||||
# Is the header compilable?
|
||||
{ echo "$as_me:$LINENO: checking $ac_header usability" >&5
|
||||
echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
$ac_includes_default
|
||||
#include <$ac_header>
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext
|
||||
if { (ac_try="$ac_compile"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_compile") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
|
||||
{ (case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest.$ac_objext'
|
||||
{ (case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_header_compiler=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_header_compiler=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||
{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
|
||||
echo "${ECHO_T}$ac_header_compiler" >&6; }
|
||||
|
||||
# Is the header present?
|
||||
{ echo "$as_me:$LINENO: checking $ac_header presence" >&5
|
||||
echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; }
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
#include <$ac_header>
|
||||
_ACEOF
|
||||
if { (ac_try="$ac_cpp conftest.$ac_ext"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } >/dev/null; then
|
||||
if test -s conftest.err; then
|
||||
ac_cpp_err=$ac_c_preproc_warn_flag
|
||||
ac_cpp_err=$ac_cpp_err$ac_c_werror_flag
|
||||
else
|
||||
ac_cpp_err=
|
||||
fi
|
||||
else
|
||||
ac_cpp_err=yes
|
||||
fi
|
||||
if test -z "$ac_cpp_err"; then
|
||||
ac_header_preproc=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_header_preproc=no
|
||||
fi
|
||||
|
||||
rm -f conftest.err conftest.$ac_ext
|
||||
{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
|
||||
echo "${ECHO_T}$ac_header_preproc" >&6; }
|
||||
|
||||
# So? What about this header?
|
||||
case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
|
||||
yes:no: )
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5
|
||||
echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5
|
||||
echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;}
|
||||
ac_header_preproc=yes
|
||||
;;
|
||||
no:yes:* )
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5
|
||||
echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5
|
||||
echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5
|
||||
echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5
|
||||
echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5
|
||||
echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5
|
||||
echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;}
|
||||
( cat <<\_ASBOX
|
||||
## ----------------------------------- ##
|
||||
## Report this to llvmbugs@cs.uiuc.edu ##
|
||||
## ----------------------------------- ##
|
||||
_ASBOX
|
||||
) | sed "s/^/$as_me: WARNING: /" >&2
|
||||
;;
|
||||
esac
|
||||
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
||||
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
eval "$as_ac_Header=\$ac_header_preproc"
|
||||
fi
|
||||
ac_res=`eval echo '${'$as_ac_Header'}'`
|
||||
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||
echo "${ECHO_T}$ac_res" >&6; }
|
||||
|
||||
fi
|
||||
if test `eval echo '${'$as_ac_Header'}'` = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for HUGE_VAL sanity" >&5
|
||||
@ -21297,7 +21470,7 @@ OCAMLOPT!$OCAMLOPT$ac_delim
|
||||
OCAMLDEP!$OCAMLDEP$ac_delim
|
||||
OCAMLDOC!$OCAMLDOC$ac_delim
|
||||
GAS!$GAS$ac_delim
|
||||
HAVE_LINK_RETAIN_SYMBOLS_FILE!$HAVE_LINK_RETAIN_SYMBOLS_FILE$ac_delim
|
||||
HAVE_LINK_VERSION_SCRIPT!$HAVE_LINK_VERSION_SCRIPT$ac_delim
|
||||
INSTALL_LTDL_TRUE!$INSTALL_LTDL_TRUE$ac_delim
|
||||
INSTALL_LTDL_FALSE!$INSTALL_LTDL_FALSE$ac_delim
|
||||
CONVENIENCE_LTDL_TRUE!$CONVENIENCE_LTDL_TRUE$ac_delim
|
||||
|
@ -31,6 +31,7 @@
|
||||
<li><a href="#chaining"><tt>AliasAnalysis</tt> chaining behavior</a></li>
|
||||
<li><a href="#updating">Updating analysis results for transformations</a></li>
|
||||
<li><a href="#implefficiency">Efficiency Issues</a></li>
|
||||
<li><a href="#passmanager">Pass Manager Issues</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@ -116,6 +117,11 @@ as the actual <tt>call</tt> or <tt>invoke</tt> instructions that performs the
|
||||
call. The <tt>AliasAnalysis</tt> interface also exposes some helper methods
|
||||
which allow you to get mod/ref information for arbitrary instructions.</p>
|
||||
|
||||
<p>All <tt>AliasAnalysis</tt> interfaces require that in queries involving
|
||||
multiple values, values which are not
|
||||
<a href="LangRef.html#constants">constants</a> are all defined within the
|
||||
same function.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
@ -180,9 +186,13 @@ that the accesses alias.</p>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
The <tt>alias</tt> method is the primary interface used to determine whether or
|
||||
not two memory objects alias each other. It takes two memory objects as input
|
||||
and returns MustAlias, MayAlias, or NoAlias as appropriate.
|
||||
<p>The <tt>alias</tt> method is the primary interface used to determine whether
|
||||
or not two memory objects alias each other. It takes two memory objects as
|
||||
input and returns MustAlias, MayAlias, or NoAlias as appropriate.</p>
|
||||
|
||||
<p>Like all <tt>AliasAnalysis</tt> interfaces, the <tt>alias</tt> method requires
|
||||
that either the two pointer values be defined within the same function, or at
|
||||
least one of the values is a <a href="LangRef.html#constants">constant</a>.</p>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
@ -191,12 +201,18 @@ and returns MustAlias, MayAlias, or NoAlias as appropriate.
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
<p>The NoAlias response is used when the two pointers refer to distinct objects,
|
||||
regardless of whether the pointers compare equal. For example, freed pointers
|
||||
don't alias any pointers that were allocated afterwards. As a degenerate case,
|
||||
pointers returned by malloc(0) have no bytes for an object, and are considered
|
||||
NoAlias even when malloc returns the same pointer. The same rule applies to
|
||||
NULL pointers.</p>
|
||||
<p>The NoAlias response may be used when there is never an immediate dependence
|
||||
between any memory reference <i>based</i> on one pointer and any memory
|
||||
reference <i>based</i> the other. The most obvious example is when the two
|
||||
pointers point to non-overlapping memory ranges. Another is when the two
|
||||
pointers are only ever used for reading memory. Another is when the memory is
|
||||
freed and reallocated between accesses through one pointer and accesses through
|
||||
the other -- in this case, there is a dependence, but it's mediated by the free
|
||||
and reallocation.</p>
|
||||
|
||||
<p>As an exception to this is with the
|
||||
<a href="LangRef.html#noalias"><tt>noalias</tt></a> keyword; the "irrelevant"
|
||||
dependencies are ignored.</p>
|
||||
|
||||
<p>The MayAlias response is used whenever the two pointers might refer to the
|
||||
same object. If the two memory objects overlap, but do not start at the same
|
||||
@ -502,6 +518,45 @@ method as possible (within reason).</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
<a name="passmanager">Pass Manager Issues</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>PassManager support for alternative AliasAnalysis implementation
|
||||
has some issues.</p>
|
||||
|
||||
<p>There is no way to override the default alias analysis. It would
|
||||
be very useful to be able to do something like "opt -my-aa -O2" and
|
||||
have it use -my-aa for all passes which need AliasAnalysis, but there
|
||||
is currently no support for that, short of changing the source code
|
||||
and recompiling. Similarly, there is also no way of setting a chain
|
||||
of analyses as the default.</p>
|
||||
|
||||
<p>There is no way for transform passes to declare that they preserve
|
||||
<tt>AliasAnalysis</tt> implementations. The <tt>AliasAnalysis</tt>
|
||||
interface includes <tt>deleteValue</tt> and <tt>copyValue</tt> methods
|
||||
which are intended to allow a pass to keep an AliasAnalysis consistent,
|
||||
however there's no way for a pass to declare in its
|
||||
<tt>getAnalysisUsage</tt> that it does so. Some passes attempt to use
|
||||
<tt>AU.addPreserved<AliasAnalysis></tt>, however this doesn't
|
||||
actually have any effect.</tt>
|
||||
|
||||
<p><tt>AliasAnalysisCounter</tt> (<tt>-count-aa</tt>) and <tt>AliasDebugger</tt>
|
||||
(<tt>-debug-aa</tt>) are implemented as <tt>ModulePass</tt> classes, so if your
|
||||
alias analysis uses <tt>FunctionPass</tt>, it won't be able to use
|
||||
these utilities. If you try to use them, the pass manager will
|
||||
silently route alias analysis queries directly to
|
||||
<tt>BasicAliasAnalysis</tt> instead.</p>
|
||||
|
||||
<p>Similarly, the <tt>opt -p</tt> option introduces <tt>ModulePass</tt>
|
||||
passes between each pass, which prevents the use of <tt>FunctionPass</tt>
|
||||
alias analysis passes.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<div class="doc_section">
|
||||
<a name="using">Using alias analysis results</a>
|
||||
@ -749,6 +804,19 @@ module, it is not part of the LLVM core.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="scev-aa">The <tt>-scev-aa</tt> pass</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<p>The <tt>-scev-aa</tt> pass implements AliasAnalysis queries by
|
||||
translating them into ScalarEvolution queries. This gives it a
|
||||
more complete understanding of <tt>getelementptr</tt> instructions
|
||||
and loop induction variables than other alias analyses have.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
<div class="doc_subsection">
|
||||
@ -930,7 +998,7 @@ analysis directly.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-07-07 16:27:09 +0200 (Wed, 07 Jul 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -1594,22 +1594,22 @@ bool RegMapping_Fer::compatible_class(MachineFunction &mf,
|
||||
different register allocators:</p>
|
||||
|
||||
<ul>
|
||||
<li><i>Simple</i> — This is a very simple implementation that does not
|
||||
keep values in registers across instructions. This register allocator
|
||||
immediately spills every value right after it is computed, and reloads all
|
||||
used operands from memory to temporary registers before each
|
||||
instruction.</li>
|
||||
|
||||
<li><i>Local</i> — This register allocator is an improvement on the
|
||||
<i>Simple</i> implementation. It allocates registers on a basic block
|
||||
level, attempting to keep values in registers and reusing registers as
|
||||
appropriate.</li>
|
||||
|
||||
<li><i>Linear Scan</i> — <i>The default allocator</i>. This is the
|
||||
well-know linear scan register allocator. Whereas the
|
||||
<i>Simple</i> and <i>Local</i> algorithms use a direct mapping
|
||||
implementation technique, the <i>Linear Scan</i> implementation
|
||||
uses a spiller in order to place load and stores.</li>
|
||||
|
||||
<li><i>Fast</i> — This register allocator is the default for debug
|
||||
builds. It allocates registers on a basic block level, attempting to keep
|
||||
values in registers and reusing registers as appropriate.</li>
|
||||
|
||||
<li><i>PBQP</i> — A Partitioned Boolean Quadratic Programming (PBQP)
|
||||
based register allocator. This allocator works by constructing a PBQP
|
||||
problem representing the register allocation problem under consideration,
|
||||
solving this using a PBQP solver, and mapping the solution back to a
|
||||
register assignment.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>The type of register allocator used in <tt>llc</tt> can be chosen with the
|
||||
@ -1617,9 +1617,9 @@ bool RegMapping_Fer::compatible_class(MachineFunction &mf,
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
$ llc -regalloc=simple file.bc -o sp.s;
|
||||
$ llc -regalloc=local file.bc -o lc.s;
|
||||
$ llc -regalloc=linearscan file.bc -o ln.s;
|
||||
$ llc -regalloc=fast file.bc -o fa.s;
|
||||
$ llc -regalloc=pbqp file.bc -o pbqp.s;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -2162,7 +2162,7 @@ MOVSX32rm16 -> movsx, 32-bit register, 16-bit memory
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-15 23:58:33 +0200 (Tue, 15 Jun 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -9,87 +9,24 @@
|
||||
|
||||
<div class="doc_title">Debugging JITed Code With GDB</div>
|
||||
<ol>
|
||||
<li><a href="#introduction">Introduction</a></li>
|
||||
<li><a href="#quickstart">Quickstart</a></li>
|
||||
<li><a href="#example">Example with clang and lli</a></li>
|
||||
<li><a href="#example">Example usage</a></li>
|
||||
<li><a href="#background">Background</a></li>
|
||||
</ol>
|
||||
<div class="doc_author">Written by Reid Kleckner</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_section"><a name="introduction">Introduction</a></div>
|
||||
<div class="doc_section"><a name="example">Example usage</a></div>
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_text">
|
||||
|
||||
<p>Without special runtime support, debugging dynamically generated code with
|
||||
GDB (as well as most debuggers) can be quite painful. Debuggers generally read
|
||||
debug information from the object file of the code, but for JITed code, there is
|
||||
no such file to look for.
|
||||
<p>In order to debug code JITed by LLVM, you need GDB 7.0 or newer, which is
|
||||
available on most modern distributions of Linux. The version of GDB that Apple
|
||||
ships with XCode has been frozen at 6.3 for a while. LLDB may be a better
|
||||
option for debugging JITed code on Mac OS X.
|
||||
</p>
|
||||
|
||||
<p>Depending on the architecture, this can impact the debugging experience in
|
||||
different ways. For example, on most 32-bit x86 architectures, you can simply
|
||||
compile with -fno-omit-framepointer for GCC and -fdisable-fp-elim for LLVM.
|
||||
When GDB creates a backtrace, it can properly unwind the stack, but the stack
|
||||
frames owned by JITed code have ??'s instead of the appropriate symbol name.
|
||||
However, on Linux x86_64 in particular, GDB relies on the DWARF CFA debug
|
||||
information to unwind the stack, so even if you compile your program to leave
|
||||
the frame pointer untouched, GDB will usually be unable to unwind the stack past
|
||||
any JITed code stack frames.
|
||||
</p>
|
||||
|
||||
<p>In order to communicate the necessary debug info to GDB, an interface for
|
||||
registering JITed code with debuggers has been designed and implemented for
|
||||
GDB and LLVM. At a high level, whenever LLVM generates new machine code, it
|
||||
also generates an object file in memory containing the debug information. LLVM
|
||||
then adds the object file to the global list of object files and calls a special
|
||||
function (__jit_debug_register_code) marked noinline that GDB knows about. When
|
||||
GDB attaches to a process, it puts a breakpoint in this function and loads all
|
||||
of the object files in the global list. When LLVM calls the registration
|
||||
function, GDB catches the breakpoint signal, loads the new object file from
|
||||
LLVM's memory, and resumes the execution. In this way, GDB can get the
|
||||
necessary debug information.
|
||||
</p>
|
||||
|
||||
<p>At the time of this writing, LLVM only supports architectures that use ELF
|
||||
object files and it only generates symbols and DWARF CFA information. However,
|
||||
it would be easy to add more information to the object file, so we don't need to
|
||||
coordinate with GDB to get better debug information.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_section"><a name="quickstart">Quickstart</a></div>
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_text">
|
||||
|
||||
<p>In order to debug code JITed by LLVM, you need to install a recent version
|
||||
of GDB. The interface was added on 2009-08-19, so you need a snapshot of GDB
|
||||
more recent than that. Either download a snapshot of GDB or checkout CVS as
|
||||
instructed <a href="http://www.gnu.org/software/gdb/current/">here</a>. Here
|
||||
are the commands for doing a checkout and building the code:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
$ cvs -z 3 -d :pserver:anoncvs@sourceware.org:/cvs/src co gdb
|
||||
$ mv src gdb # You probably don't want this checkout called "src".
|
||||
$ cd gdb
|
||||
$ ./configure --prefix="$GDB_INSTALL"
|
||||
$ make
|
||||
$ make install
|
||||
</pre>
|
||||
|
||||
<p>You can then use -jit-emit-debug in the LLVM command line arguments to enable
|
||||
the interface.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_section"><a name="example">Example with clang and lli</a></div>
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_text">
|
||||
|
||||
<p>For example, consider debugging running lli on the following C code in
|
||||
foo.c:
|
||||
<p>Consider debugging the following code compiled with clang and run through
|
||||
lli:
|
||||
</p>
|
||||
|
||||
<pre class="doc_code">
|
||||
@ -119,7 +56,9 @@ trace at the crash:
|
||||
<pre class="doc_code">
|
||||
# Compile foo.c to bitcode. You can use either clang or llvm-gcc with this
|
||||
# command line. Both require -fexceptions, or the calls are all marked
|
||||
# 'nounwind' which disables DWARF CFA info.
|
||||
# 'nounwind' which disables DWARF exception handling info. Custom frontends
|
||||
# should avoid adding this attribute to JITed code, since it interferes with
|
||||
# DWARF CFA generation at the moment.
|
||||
$ clang foo.c -fexceptions -emit-llvm -c -o foo.bc
|
||||
|
||||
# Run foo.bc under lli with -jit-emit-debug. If you built lli in debug mode,
|
||||
@ -143,18 +82,60 @@ Program received signal SIGSEGV, Segmentation fault.
|
||||
#3 0x00007ffff7f5502a in main ()
|
||||
#4 0x00000000007c0225 in llvm::JIT::runFunction(llvm::Function*,
|
||||
std::vector<llvm::GenericValue,
|
||||
std::allocator<llvm::GenericValue> > const&) ()
|
||||
std::allocator<llvm::GenericValue> > const&) ()
|
||||
#5 0x00000000007d6d98 in
|
||||
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
|
||||
std::vector<std::string,
|
||||
std::allocator<std::string> > const&, char const* const*) ()
|
||||
std::allocator<std::string> > const&, char const* const*) ()
|
||||
#6 0x00000000004dab76 in main ()
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>As you can see, GDB can correctly unwind the stack and has the appropriate
|
||||
function names.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_section"><a name="background">Background</a></div>
|
||||
<!--=========================================================================-->
|
||||
<div class="doc_text">
|
||||
|
||||
<p>Without special runtime support, debugging dynamically generated code with
|
||||
GDB (as well as most debuggers) can be quite painful. Debuggers generally read
|
||||
debug information from the object file of the code, but for JITed code, there is
|
||||
no such file to look for.
|
||||
</p>
|
||||
|
||||
<p>Depending on the architecture, this can impact the debugging experience in
|
||||
different ways. For example, on most 32-bit x86 architectures, you can simply
|
||||
compile with -fno-omit-frame-pointer for GCC and -disable-fp-elim for LLVM.
|
||||
When GDB creates a backtrace, it can properly unwind the stack, but the stack
|
||||
frames owned by JITed code have ??'s instead of the appropriate symbol name.
|
||||
However, on Linux x86_64 in particular, GDB relies on the DWARF call frame
|
||||
address (CFA) debug information to unwind the stack, so even if you compile
|
||||
your program to leave the frame pointer untouched, GDB will usually be unable
|
||||
to unwind the stack past any JITed code stack frames.
|
||||
</p>
|
||||
|
||||
<p>In order to communicate the necessary debug info to GDB, an interface for
|
||||
registering JITed code with debuggers has been designed and implemented for
|
||||
GDB and LLVM. At a high level, whenever LLVM generates new machine code, it
|
||||
also generates an object file in memory containing the debug information. LLVM
|
||||
then adds the object file to the global list of object files and calls a special
|
||||
function (__jit_debug_register_code) marked noinline that GDB knows about. When
|
||||
GDB attaches to a process, it puts a breakpoint in this function and loads all
|
||||
of the object files in the global list. When LLVM calls the registration
|
||||
function, GDB catches the breakpoint signal, loads the new object file from
|
||||
LLVM's memory, and resumes the execution. In this way, GDB can get the
|
||||
necessary debug information.
|
||||
</p>
|
||||
|
||||
<p>At the time of this writing, LLVM only supports architectures that use ELF
|
||||
object files and it only generates symbols and DWARF CFA information. However,
|
||||
it would be easy to add more information to the object file, so we don't need to
|
||||
coordinate with GDB to get better debug information.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
<hr>
|
||||
@ -165,7 +146,7 @@ function names.
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
<a href="mailto:reid.kleckner@gmail.com">Reid Kleckner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2009-01-01 23:10:51 -0800 (Thu, 01 Jan 2009) $
|
||||
Last modified: $Date: 2010-07-07 22:16:45 +0200 (Wed, 07 Jul 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -404,7 +404,7 @@
|
||||
<div class="doc_text">
|
||||
|
||||
<pre>
|
||||
i8* %<a href="#llvm_eh_exception">llvm.eh.exception</a>( )
|
||||
i8* %<a href="#llvm_eh_exception">llvm.eh.exception</a>()
|
||||
</pre>
|
||||
|
||||
<p>This intrinsic returns a pointer to the exception structure.</p>
|
||||
@ -518,7 +518,7 @@
|
||||
<div class="doc_text">
|
||||
|
||||
<pre>
|
||||
i8* %<a href="#llvm_eh_sjlj_lsda">llvm.eh.sjlj.lsda</a>( )
|
||||
i8* %<a href="#llvm_eh_sjlj_lsda">llvm.eh.sjlj.lsda</a>()
|
||||
</pre>
|
||||
|
||||
<p>Used for SJLJ based exception handling, the <a href="#llvm_eh_sjlj_lsda">
|
||||
@ -619,7 +619,7 @@
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-26 18:21:41 +0200 (Wed, 26 May 2010) $
|
||||
Last modified: $Date: 2010-05-28 19:07:41 +0200 (Fri, 28 May 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -803,7 +803,7 @@ define fastcc void @foo() {
|
||||
ret void
|
||||
}
|
||||
define void @bar() {
|
||||
call void @foo( )
|
||||
call void @foo()
|
||||
ret void
|
||||
}
|
||||
</pre>
|
||||
@ -931,7 +931,7 @@ F.i:
|
||||
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-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-05-28 19:07:41 +0200 (Fri, 28 May 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -64,7 +64,8 @@
|
||||
|
||||
<div class="doc_text">
|
||||
<p>This document seeks to dispel the mystery and confusion surrounding LLVM's
|
||||
GetElementPtr (GEP) instruction. Questions about the wily GEP instruction are
|
||||
<a href="LangRef.html#i_getelementptr">GetElementPtr</a> (GEP) instruction.
|
||||
Questions about the wily GEP instruction are
|
||||
probably the most frequently occurring questions once a developer gets down to
|
||||
coding with LLVM. Here we lay out the sources of confusion and show that the
|
||||
GEP instruction is really quite simple.
|
||||
@ -653,7 +654,8 @@ idx3 = (char*) &MyVar + 8
|
||||
<li>Support C, C-like languages, and languages which can be
|
||||
conceptually lowered into C (this covers a lot).</li>
|
||||
<li>Support optimizations such as those that are common in
|
||||
C compilers.</li>
|
||||
C compilers. In particular, GEP is a cornerstone of LLVM's
|
||||
<a href="LangRef.html#pointeraliasing">pointer aliasing model</a>.</li>
|
||||
<li>Provide a consistent method for computing addresses so that
|
||||
address computations don't need to be a part of load and
|
||||
store instructions in the IR.</li>
|
||||
@ -728,7 +730,7 @@ idx3 = (char*) &MyVar + 8
|
||||
<a href="http://validator.w3.org/check/referer"><img
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br/>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-07-06 17:26:33 +0200 (Tue, 06 Jul 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1137,13 +1137,13 @@ platforms or configurations using the same source tree.</p>
|
||||
named after the build type:</p>
|
||||
|
||||
<dl>
|
||||
<dt>Debug Builds
|
||||
<dt>Debug Builds with assertions enabled (the default)
|
||||
<dd>
|
||||
<dl>
|
||||
<dt>Tools
|
||||
<dd><tt><i>OBJ_ROOT</i>/Debug/bin</tt>
|
||||
<dd><tt><i>OBJ_ROOT</i>/Debug+Asserts/bin</tt>
|
||||
<dt>Libraries
|
||||
<dd><tt><i>OBJ_ROOT</i>/Debug/lib</tt>
|
||||
<dd><tt><i>OBJ_ROOT</i>/Debug+Asserts/lib</tt>
|
||||
</dl>
|
||||
<br><br>
|
||||
|
||||
@ -1673,7 +1673,7 @@ out:</p>
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.x10sys.com/rspencer/">Reid Spencer</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-19 09:00:17 +0200 (Wed, 19 May 2010) $
|
||||
Last modified: $Date: 2010-07-08 10:27:18 +0200 (Thu, 08 Jul 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -213,13 +213,13 @@ Building the Release</a></div>
|
||||
|
||||
<div class="doc_text">
|
||||
The build of <tt>llvm</tt>, <tt>llvm-gcc</tt>, and <tt>clang</tt> must be free
|
||||
of errors and warnings in both debug, release, and release-asserts builds.
|
||||
of errors and warnings in both debug, release+asserts, and release builds.
|
||||
If all builds are clean, then the release passes build qualification.
|
||||
|
||||
<ol>
|
||||
<li>debug: ENABLE_OPTIMIZED=0</li>
|
||||
<li>release: ENABLE_OPTIMIZED=1</li>
|
||||
<li>release-asserts: ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1</li>
|
||||
<li>release+asserts: ENABLE_OPTIMIZED=1</li>
|
||||
<li>release: ENABLE_OPTIMIZED=1 DISABLE_ASSERTIONS=1</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
@ -227,7 +227,7 @@ If all builds are clean, then the release passes build qualification.
|
||||
<div class="doc_subsubsection"><a name="build">Build LLVM</a></div>
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
Build both debug, release (optimized), and release-asserts versions of
|
||||
Build both debug, release+asserts (optimized), and release versions of
|
||||
LLVM on all supported platforms. Direction to build llvm are
|
||||
<a href="http://llvm.org/docs/GettingStarted.html#quickstart">here</a>.
|
||||
</p>
|
||||
@ -264,7 +264,7 @@ If all builds are clean, then the release passes build qualification.
|
||||
Binary Distribution</a></div>
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
Creating the Clang binary distribution (debug/release/release-asserts) requires
|
||||
Creating the Clang binary distribution (debug/release/release) requires
|
||||
performing the following steps for each supported platform:
|
||||
</p>
|
||||
|
||||
@ -429,7 +429,7 @@ Qualification Details</a></div>
|
||||
</a></div>
|
||||
<div class="doc_text">
|
||||
<p>
|
||||
The final stages of the release process involving taging the release branch,
|
||||
The final stages of the release process involving tagging the release branch,
|
||||
updating documentation that refers to the release, and updating the demo
|
||||
page.</p>
|
||||
<p>FIXME: Add a note if anything needs to be done to the clang website.
|
||||
@ -517,7 +517,7 @@ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XX \
|
||||
src="http://www.w3.org/Icons/valid-html401-blue" alt="Valid HTML 4.01"></a>
|
||||
<a href="http://llvm.cs.uiuc.edu">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-07-07 09:48:00 +0200 (Wed, 07 Jul 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -652,7 +652,7 @@
|
||||
the profiled tools (<tt>gmon.out</tt>).</dd>
|
||||
<dt><a name="DISABLE_ASSERTIONS"><tt>DISABLE_ASSERTIONS</tt></a></dt>
|
||||
<dd>If set to any value, causes the build to disable assertions, even if
|
||||
building a release or profile build. This will exclude all assertion check
|
||||
building a debug or profile build. This will exclude all assertion check
|
||||
code from the build. LLVM will execute faster, but with little help when
|
||||
things go wrong.</dd>
|
||||
<dt><a name="EXPERIMENTAL_DIRS"><tt>EXPERIMENTAL_DIRS</tt></a></dt>
|
||||
@ -1025,7 +1025,7 @@
|
||||
|
||||
<a href="mailto:rspencer@x10sys.com">Reid Spencer</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-07-07 09:48:00 +0200 (Wed, 07 Jul 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
708
docs/Passes.html
708
docs/Passes.html
File diff suppressed because it is too large
Load Diff
@ -401,7 +401,7 @@ height="369">
|
||||
metadata, ;; Reference to type descriptor
|
||||
i1, ;; True if the global is local to compile unit (static)
|
||||
i1, ;; True if the global is defined in the compile unit (not extern)
|
||||
{ }* ;; Reference to the global variable
|
||||
{}* ;; Reference to the global variable
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -433,6 +433,13 @@ provide details such as name, type and where the variable is defined.</p>
|
||||
metadata, ;; Reference to type descriptor
|
||||
i1, ;; True if the global is local to compile unit (static)
|
||||
i1 ;; True if the global is defined in the compile unit (not extern)
|
||||
i32 ;; Virtuality, e.g. dwarf::DW_VIRTUALITY__virtual
|
||||
i32 ;; Index into a virtual function
|
||||
metadata, ;; indicates which base type contains the vtable pointer for the
|
||||
;; derived class
|
||||
i1 ;; isArtificial
|
||||
i1 ;; isOptimized
|
||||
Function *;; Pointer to LLVM function
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
@ -782,11 +789,11 @@ DW_TAG_return_variable = 258
|
||||
|
||||
<div class="doc_text">
|
||||
<pre>
|
||||
void %<a href="#format_common_declare">llvm.dbg.declare</a>( { } *, metadata )
|
||||
void %<a href="#format_common_declare">llvm.dbg.declare</a>({}*, metadata)
|
||||
</pre>
|
||||
|
||||
<p>This intrinsic provides information about a local element (ex. variable.) The
|
||||
first argument is the alloca for the variable, cast to a <tt>{ }*</tt>. The
|
||||
first argument is the alloca for the variable, cast to a <tt>{}*</tt>. The
|
||||
second argument is
|
||||
the <tt>%<a href="#format_variables">llvm.dbg.variable</a></tt> containing
|
||||
the description of the variable. </p>
|
||||
@ -800,7 +807,7 @@ DW_TAG_return_variable = 258
|
||||
|
||||
<div class="doc_text">
|
||||
<pre>
|
||||
void %<a href="#format_common_value">llvm.dbg.value</a>( metadata, i64, metadata )
|
||||
void %<a href="#format_common_value">llvm.dbg.value</a>(metadata, i64, metadata)
|
||||
</pre>
|
||||
|
||||
<p>This intrinsic provides information when a user source variable is set to a
|
||||
@ -854,14 +861,14 @@ entry:
|
||||
%X = alloca i32, align 4 ; <i32*> [#uses=4]
|
||||
%Y = alloca i32, align 4 ; <i32*> [#uses=4]
|
||||
%Z = alloca i32, align 4 ; <i32*> [#uses=3]
|
||||
%0 = bitcast i32* %X to { }* ; <{ }*> [#uses=1]
|
||||
call void @llvm.dbg.declare({ }* %0, metadata !0), !dbg !7
|
||||
%0 = bitcast i32* %X to {}* ; <{}*> [#uses=1]
|
||||
call void @llvm.dbg.declare({}* %0, metadata !0), !dbg !7
|
||||
store i32 21, i32* %X, !dbg !8
|
||||
%1 = bitcast i32* %Y to { }* ; <{ }*> [#uses=1]
|
||||
call void @llvm.dbg.declare({ }* %1, metadata !9), !dbg !10
|
||||
%1 = bitcast i32* %Y to {}* ; <{}*> [#uses=1]
|
||||
call void @llvm.dbg.declare({}* %1, metadata !9), !dbg !10
|
||||
store i32 22, i32* %Y, !dbg !11
|
||||
%2 = bitcast i32* %Z to { }* ; <{ }*> [#uses=1]
|
||||
call void @llvm.dbg.declare({ }* %2, metadata !12), !dbg !14
|
||||
%2 = bitcast i32* %Z to {}* ; <{}*> [#uses=1]
|
||||
call void @llvm.dbg.declare({}* %2, metadata !12), !dbg !14
|
||||
store i32 23, i32* %Z, !dbg !15
|
||||
%tmp = load i32* %X, !dbg !16 ; <i32> [#uses=1]
|
||||
%tmp1 = load i32* %Y, !dbg !16 ; <i32> [#uses=1]
|
||||
@ -872,7 +879,7 @@ entry:
|
||||
ret void, !dbg !18
|
||||
}
|
||||
|
||||
declare void @llvm.dbg.declare({ }*, metadata) nounwind readnone
|
||||
declare void @llvm.dbg.declare({}*, metadata) nounwind readnone
|
||||
|
||||
!0 = metadata !{i32 459008, metadata !1, metadata !"X",
|
||||
metadata !3, i32 2, metadata !6}; [ DW_TAG_auto_variable ]
|
||||
@ -914,7 +921,7 @@ declare void @llvm.dbg.declare({ }*, metadata) nounwind readnone
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
call void @llvm.dbg.declare({ }* %0, metadata !0), !dbg !7
|
||||
call void @llvm.dbg.declare({}* %0, metadata !0), !dbg !7
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -949,7 +956,7 @@ call void @llvm.dbg.declare({ }* %0, metadata !0), !dbg !7
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
call void @llvm.dbg.declare({ }* %2, metadata !12), !dbg !14
|
||||
call void @llvm.dbg.declare({}* %2, metadata !12), !dbg !14
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
@ -1773,7 +1780,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-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-05 00:49:55 +0200 (Sat, 05 Jun 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -144,7 +144,6 @@ file prints this (at the time of this writing):</p>
|
||||
<b>bit</b> mayLoad = 0;
|
||||
<b>bit</b> mayStore = 0;
|
||||
<b>bit</b> isImplicitDef = 0;
|
||||
<b>bit</b> isTwoAddress = 1;
|
||||
<b>bit</b> isConvertibleToThreeAddress = 1;
|
||||
<b>bit</b> isCommutable = 1;
|
||||
<b>bit</b> isTerminator = 0;
|
||||
@ -422,11 +421,12 @@ class. This operation is analogous to $(foreach) in GNU make.</dd>
|
||||
<dt><tt>!null(a)</tt></dt>
|
||||
<dd>An integer {0,1} indicating whether list 'a' is empty.</dd>
|
||||
<dt><tt>!if(a,b,c)</tt></dt>
|
||||
<dd>'b' if the result of integer operator 'a' is nonzero, 'c' otherwise.</dd>
|
||||
<dd>'b' if the result of 'int' or 'bit' operator 'a' is nonzero,
|
||||
'c' otherwise.</dd>
|
||||
<dt><tt>!eq(a,b)</tt></dt>
|
||||
<dd>Integer one if string a is equal to string b, zero otherwise. This
|
||||
only operates on string objects. Use !cast<string> to compare other
|
||||
types of objects.</dd>
|
||||
only operates on string, int and bit objects. Use !cast<string> to
|
||||
compare other types of objects.</dd>
|
||||
</dl>
|
||||
|
||||
<p>Note that all of the values have rules specifying how they convert to values
|
||||
@ -687,6 +687,91 @@ Here is an example TableGen fragment that shows this idea:
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
A defm can also be used inside a multiclass providing several levels of
|
||||
multiclass instanciations.
|
||||
</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>class</b> Instruction<bits<4> opc, string Name> {
|
||||
bits<4> opcode = opc;
|
||||
string name = Name;
|
||||
}
|
||||
|
||||
<b>multiclass</b> basic_r<bits<4> opc> {
|
||||
<b>def</b> rr : Instruction<opc, "rr">;
|
||||
<b>def</b> rm : Instruction<opc, "rm">;
|
||||
}
|
||||
|
||||
<b>multiclass</b> basic_s<bits<4> opc> {
|
||||
<b>defm</b> SS : basic_r<opc>;
|
||||
<b>defm</b> SD : basic_r<opc>;
|
||||
<b>def</b> X : Instruction<opc, "x">;
|
||||
}
|
||||
|
||||
<b>multiclass</b> basic_p<bits<4> opc> {
|
||||
<b>defm</b> PS : basic_r<opc>;
|
||||
<b>defm</b> PD : basic_r<opc>;
|
||||
<b>def</b> Y : Instruction<opc, "y">;
|
||||
}
|
||||
|
||||
<b>defm</b> ADD : basic_s<0xf>, basic_p<0xf>;
|
||||
...
|
||||
|
||||
<i>// Results</i>
|
||||
<b>def</b> ADDPDrm { ...
|
||||
<b>def</b> ADDPDrr { ...
|
||||
<b>def</b> ADDPSrm { ...
|
||||
<b>def</b> ADDPSrr { ...
|
||||
<b>def</b> ADDSDrm { ...
|
||||
<b>def</b> ADDSDrr { ...
|
||||
<b>def</b> ADDY { ...
|
||||
<b>def</b> ADDX { ...
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
defm declarations can inherit from classes too, the
|
||||
rule to follow is that the class list must start after the
|
||||
last multiclass, and there must be at least one multiclass
|
||||
before them.
|
||||
</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>class</b> XD { bits<4> Prefix = 11; }
|
||||
<b>class</b> XS { bits<4> Prefix = 12; }
|
||||
|
||||
<b>class</b> I<bits<4> op> {
|
||||
bits<4> opcode = op;
|
||||
}
|
||||
|
||||
<b>multiclass</b> R {
|
||||
<b>def</b> rr : I<4>;
|
||||
<b>def</b> rm : I<2>;
|
||||
}
|
||||
|
||||
<b>multiclass</b> Y {
|
||||
<b>defm</b> SS : R, XD;
|
||||
<b>defm</b> SD : R, XS;
|
||||
}
|
||||
|
||||
<b>defm</b> Instr : Y;
|
||||
|
||||
<i>// Results</i>
|
||||
<b>def</b> InstrSDrm {
|
||||
bits<4> opcode = { 0, 0, 1, 0 };
|
||||
bits<4> Prefix = { 1, 1, 0, 0 };
|
||||
}
|
||||
...
|
||||
<b>def</b> InstrSSrr {
|
||||
bits<4> opcode = { 0, 1, 0, 0 };
|
||||
bits<4> Prefix = { 1, 0, 1, 1 };
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ======================================================================= -->
|
||||
@ -754,6 +839,32 @@ examples:</p>
|
||||
need to be added to several records, and the records do not otherwise need to be
|
||||
opened, as in the case with the <tt>CALL*</tt> instructions above.</p>
|
||||
|
||||
<p>It's also possible to use "let" expressions inside multiclasses, providing
|
||||
more ways to factor out commonality from the records, specially if using
|
||||
several levels of multiclass instanciations. This also avoids the need of using
|
||||
"let" expressions within subsequent records inside a multiclass.</p>
|
||||
|
||||
<div class="doc_code">
|
||||
<pre>
|
||||
<b>multiclass </b>basic_r<bits<4> opc> {
|
||||
<b>let </b>Predicates = [HasSSE2] in {
|
||||
<b>def </b>rr : Instruction<opc, "rr">;
|
||||
<b>def </b>rm : Instruction<opc, "rm">;
|
||||
}
|
||||
<b>let </b>Predicates = [HasSSE3] in
|
||||
<b>def </b>rx : Instruction<opc, "rx">;
|
||||
}
|
||||
|
||||
<b>multiclass </b>basic_ss<bits<4> opc> {
|
||||
<b>let </b>IsDouble = 0 in
|
||||
<b>defm </b>SS : basic_r<opc>;
|
||||
|
||||
<b>let </b>IsDouble = 1 in
|
||||
<b>defm </b>SD : basic_r<opc>;
|
||||
}
|
||||
|
||||
<b>defm </b>ADD : basic_ss<0xf>;
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!-- *********************************************************************** -->
|
||||
@ -795,7 +906,7 @@ This should highlight the APIs in <tt>TableGen/Record.h</tt>.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-21 22:35:09 +0200 (Mon, 21 Jun 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -913,9 +913,6 @@ implementation in <tt>SparcRegisterInfo.cpp</tt>:
|
||||
<li><tt>getCalleeSavedRegs</tt> — Returns a list of callee-saved registers
|
||||
in the order of the desired callee-save stack frame offset.</li>
|
||||
|
||||
<li><tt>getCalleeSavedRegClasses</tt> — Returns a list of preferred
|
||||
register classes with which to spill each callee saved register.</li>
|
||||
|
||||
<li><tt>getReservedRegs</tt> — Returns a bitset indexed by physical
|
||||
register numbers, indicating if a particular register is unavailable.</li>
|
||||
|
||||
@ -1313,7 +1310,8 @@ implementation in <tt>SparcInstrInfo.cpp</tt>:
|
||||
a direct store to a stack slot, return the register number of the
|
||||
destination and the <tt>FrameIndex</tt> of the stack slot.</li>
|
||||
|
||||
<li><tt>copyRegToReg</tt> — Copy values between a pair of registers.</li>
|
||||
<li><tt>copyPhysReg</tt> — Copy values between a pair of physical
|
||||
registers.</li>
|
||||
|
||||
<li><tt>storeRegToStackSlot</tt> — Store a register value to a stack
|
||||
slot.</li>
|
||||
@ -2554,7 +2552,7 @@ with assembler.
|
||||
<a href="http://www.woo.com">Mason Woo</a> and <a href="http://misha.brukman.net">Misha Brukman</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a>
|
||||
<br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-07-11 19:01:17 +0200 (Sun, 11 Jul 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -189,18 +189,13 @@ LIBRARYNAME = Hello
|
||||
# dlopen/dlsym on the resulting library.
|
||||
LOADABLE_MODULE = 1
|
||||
|
||||
# Tell the build system which LLVM libraries your pass needs. You'll probably
|
||||
# need at least LLVMSystem.a, LLVMSupport.a, LLVMCore.a but possibly several
|
||||
# others too.
|
||||
LLVMLIBS = LLVMCore.a LLVMSupport.a LLVMSystem.a
|
||||
|
||||
# Include the makefile implementation stuff
|
||||
include $(LEVEL)/Makefile.common
|
||||
</pre></div>
|
||||
|
||||
<p>This makefile specifies that all of the <tt>.cpp</tt> files in the current
|
||||
directory are to be compiled and linked together into a
|
||||
<tt>Debug/lib/Hello.so</tt> shared object that can be dynamically loaded by
|
||||
<tt>Debug+Asserts/lib/Hello.so</tt> shared object that can be dynamically loaded by
|
||||
the <tt>opt</tt> or <tt>bugpoint</tt> tools via their <tt>-load</tt> options.
|
||||
If your operating system uses a suffix other than .so (such as windows or
|
||||
Mac OS/X), the appropriate extension will be used.</p>
|
||||
@ -337,7 +332,7 @@ is supplied as fourth argument. </p>
|
||||
|
||||
<p>Now that it's all together, compile the file with a simple "<tt>gmake</tt>"
|
||||
command in the local directory and you should get a new
|
||||
"<tt>Debug/lib/Hello.so</tt> file. Note that everything in this file is
|
||||
"<tt>Debug+Asserts/lib/Hello.so</tt> file. Note that everything in this file is
|
||||
contained in an anonymous namespace: this reflects the fact that passes are self
|
||||
contained units that do not need external interfaces (although they can have
|
||||
them) to be useful.</p>
|
||||
@ -363,7 +358,7 @@ through our transformation like this (or course, any bitcode file will
|
||||
work):</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
$ opt -load ../../../Debug/lib/Hello.so -hello < hello.bc > /dev/null
|
||||
$ opt -load ../../../Debug+Asserts/lib/Hello.so -hello < hello.bc > /dev/null
|
||||
Hello: __main
|
||||
Hello: puts
|
||||
Hello: main
|
||||
@ -380,7 +375,7 @@ interesting way, we just throw away the result of <tt>opt</tt> (sending it to
|
||||
<tt>opt</tt> with the <tt>-help</tt> option:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
$ opt -load ../../../Debug/lib/Hello.so -help
|
||||
$ opt -load ../../../Debug+Asserts/lib/Hello.so -help
|
||||
OVERVIEW: llvm .bc -> .bc modular optimizer
|
||||
|
||||
USAGE: opt [options] <input bitcode>
|
||||
@ -408,7 +403,7 @@ the execution time of your pass along with the other passes you queue up. For
|
||||
example:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
$ opt -load ../../../Debug/lib/Hello.so -hello -time-passes < hello.bc > /dev/null
|
||||
$ opt -load ../../../Debug+Asserts/lib/Hello.so -hello -time-passes < hello.bc > /dev/null
|
||||
Hello: __main
|
||||
Hello: puts
|
||||
Hello: main
|
||||
@ -1423,7 +1418,7 @@ how our <a href="#basiccode">Hello World</a> pass interacts with other passes.
|
||||
Lets try it out with the <tt>gcse</tt> and <tt>licm</tt> passes:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
$ opt -load ../../../Debug/lib/Hello.so -gcse -licm --debug-pass=Structure < hello.bc > /dev/null
|
||||
$ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -licm --debug-pass=Structure < hello.bc > /dev/null
|
||||
Module Pass Manager
|
||||
Function Pass Manager
|
||||
Dominator Set Construction
|
||||
@ -1460,7 +1455,7 @@ passes.</p>
|
||||
World</a> pass in between the two passes:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
$ opt -load ../../../Debug/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null
|
||||
$ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null
|
||||
Module Pass Manager
|
||||
Function Pass Manager
|
||||
Dominator Set Construction
|
||||
@ -1501,7 +1496,7 @@ href="#getAnalysisUsage"><tt>getAnalysisUsage</tt></a> method to our pass:</p>
|
||||
<p>Now when we run our pass, we get this output:</p>
|
||||
|
||||
<div class="doc_code"><pre>
|
||||
$ opt -load ../../../Debug/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null
|
||||
$ opt -load ../../../Debug+Asserts/lib/Hello.so -gcse -hello -licm --debug-pass=Structure < hello.bc > /dev/null
|
||||
Pass Arguments: -gcse -hello -licm
|
||||
Module Pass Manager
|
||||
Function Pass Manager
|
||||
@ -1742,8 +1737,8 @@ want:</p>
|
||||
<div class="doc_code"><pre>
|
||||
(gdb) <b>break llvm::PassManager::run</b>
|
||||
Breakpoint 1 at 0x2413bc: file Pass.cpp, line 70.
|
||||
(gdb) <b>run test.bc -load $(LLVMTOP)/llvm/Debug/lib/[libname].so -[passoption]</b>
|
||||
Starting program: opt test.bc -load $(LLVMTOP)/llvm/Debug/lib/[libname].so -[passoption]
|
||||
(gdb) <b>run test.bc -load $(LLVMTOP)/llvm/Debug+Asserts/lib/[libname].so -[passoption]</b>
|
||||
Starting program: opt test.bc -load $(LLVMTOP)/llvm/Debug+Asserts/lib/[libname].so -[passoption]
|
||||
Breakpoint 1, PassManager::run (this=0xffbef174, M=@0x70b298) at Pass.cpp:70
|
||||
70 bool PassManager::run(Module &M) { return PM->run(M); }
|
||||
(gdb)
|
||||
@ -1835,7 +1830,7 @@ Despite that, we have kept the LLVM passes SMP ready, and you should too.</p>
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-07-08 10:27:18 +0200 (Thu, 08 Jul 2010) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -200,9 +200,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -574,8 +574,8 @@ ready> <b>def bar(a) foo(a, 4.0) + bar(31337);</b>
|
||||
Read function definition:
|
||||
define double @bar(double %a) {
|
||||
entry:
|
||||
%calltmp = call double @foo( double %a, double 4.000000e+00 )
|
||||
%calltmp1 = call double @bar( double 3.133700e+04 )
|
||||
%calltmp = call double @foo(double %a, double 4.000000e+00)
|
||||
%calltmp1 = call double @bar(double 3.133700e+04)
|
||||
%addtmp = fadd double %calltmp, %calltmp1
|
||||
ret double %addtmp
|
||||
}
|
||||
@ -596,7 +596,7 @@ ready> <b>cos(1.234);</b>
|
||||
Read top-level expression:
|
||||
define double @""() {
|
||||
entry:
|
||||
%calltmp = call double @cos( double 1.234000e+00 )
|
||||
%calltmp = call double @cos(double 1.234000e+00)
|
||||
ret double %calltmp
|
||||
}
|
||||
</pre>
|
||||
@ -629,8 +629,8 @@ entry:
|
||||
|
||||
define double @bar(double %a) {
|
||||
entry:
|
||||
%calltmp = call double @foo( double %a, double 4.000000e+00 )
|
||||
%calltmp1 = call double @bar( double 3.133700e+04 )
|
||||
%calltmp = call double @foo(double %a, double 4.000000e+00)
|
||||
%calltmp1 = call double @bar(double 3.133700e+04)
|
||||
%addtmp = fadd double %calltmp, %calltmp1
|
||||
ret double %addtmp
|
||||
}
|
||||
@ -639,7 +639,7 @@ declare double @cos(double)
|
||||
|
||||
define double @""() {
|
||||
entry:
|
||||
%calltmp = call double @cos( double 1.234000e+00 )
|
||||
%calltmp = call double @cos(double 1.234000e+00)
|
||||
ret double %calltmp
|
||||
}
|
||||
</pre>
|
||||
@ -1263,7 +1263,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-14 08:09:39 +0200 (Mon, 14 Jun 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -371,7 +371,7 @@ entry:
|
||||
ready> <b>testfunc(4, 10);</b>
|
||||
define double @""() {
|
||||
entry:
|
||||
%calltmp = call double @testfunc( double 4.000000e+00, double 1.000000e+01 )
|
||||
%calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
|
||||
ret double %calltmp
|
||||
}
|
||||
|
||||
@ -410,9 +410,9 @@ ready> <b>def foo(x) sin(x)*sin(x) + cos(x)*cos(x);</b>
|
||||
Read function definition:
|
||||
define double @foo(double %x) {
|
||||
entry:
|
||||
%calltmp = call double @sin( double %x )
|
||||
%calltmp = call double @sin(double %x)
|
||||
%multmp = fmul double %calltmp, %calltmp
|
||||
%calltmp2 = call double @cos( double %x )
|
||||
%calltmp2 = call double @cos(double %x)
|
||||
%multmp4 = fmul double %calltmp2, %calltmp2
|
||||
%addtmp = fadd double %multmp, %multmp4
|
||||
ret double %addtmp
|
||||
@ -876,9 +876,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -1126,7 +1126,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-14 08:09:39 +0200 (Mon, 14 Jun 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -676,7 +676,7 @@ entry:
|
||||
loop: ; preds = %loop, %entry
|
||||
%i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
|
||||
; body
|
||||
%calltmp = call double @putchard( double 4.200000e+01 )
|
||||
%calltmp = call double @putchard(double 4.200000e+01)
|
||||
; increment
|
||||
%nextvar = fadd double %i, 1.000000e+00
|
||||
|
||||
@ -1377,9 +1377,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -1771,7 +1771,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-14 08:09:39 +0200 (Mon, 14 Jun 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -277,9 +277,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -531,7 +531,7 @@ def unary!(v)
|
||||
def unary-(v)
|
||||
0-v;
|
||||
|
||||
# Define > with the same precedence as >.
|
||||
# Define > with the same precedence as <.
|
||||
def binary> 10 (LHS RHS)
|
||||
RHS < LHS;
|
||||
|
||||
@ -1392,9 +1392,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -1808,7 +1808,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-21 22:31:30 +0200 (Mon, 21 Jun 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -558,10 +558,10 @@ then: ; preds = %entry
|
||||
else: ; preds = %entry
|
||||
<b>%x3 = load double* %x1</b>
|
||||
%subtmp = fsub double %x3, 1.000000e+00
|
||||
%calltmp = call double @fib( double %subtmp )
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
<b>%x4 = load double* %x1</b>
|
||||
%subtmp5 = fsub double %x4, 2.000000e+00
|
||||
%calltmp6 = call double @fib( double %subtmp5 )
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
br label %ifcont
|
||||
|
||||
@ -596,9 +596,9 @@ then:
|
||||
|
||||
else:
|
||||
%subtmp = fsub double <b>%x</b>, 1.000000e+00
|
||||
%calltmp = call double @fib( double %subtmp )
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
%subtmp5 = fsub double <b>%x</b>, 2.000000e+00
|
||||
%calltmp6 = call double @fib( double %subtmp5 )
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
br label %ifcont
|
||||
|
||||
@ -626,9 +626,9 @@ entry:
|
||||
|
||||
else:
|
||||
%subtmp = fsub double %x, 1.000000e+00
|
||||
%calltmp = call double @fib( double %subtmp )
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
%subtmp5 = fsub double %x, 2.000000e+00
|
||||
%calltmp6 = call double @fib( double %subtmp5 )
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
ret double %addtmp
|
||||
|
||||
@ -1672,9 +1672,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -2158,7 +2158,7 @@ int main() {
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-14 08:09:39 +0200 (Mon, 14 Jun 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -524,8 +524,8 @@ ready> <b>def bar(a) foo(a, 4.0) + bar(31337);</b>
|
||||
Read function definition:
|
||||
define double @bar(double %a) {
|
||||
entry:
|
||||
%calltmp = call double @foo( double %a, double 4.000000e+00 )
|
||||
%calltmp1 = call double @bar( double 3.133700e+04 )
|
||||
%calltmp = call double @foo(double %a, double 4.000000e+00)
|
||||
%calltmp1 = call double @bar(double 3.133700e+04)
|
||||
%addtmp = fadd double %calltmp, %calltmp1
|
||||
ret double %addtmp
|
||||
}
|
||||
@ -546,7 +546,7 @@ ready> <b>cos(1.234);</b>
|
||||
Read top-level expression:
|
||||
define double @""() {
|
||||
entry:
|
||||
%calltmp = call double @cos( double 1.234000e+00 )
|
||||
%calltmp = call double @cos(double 1.234000e+00)
|
||||
ret double %calltmp
|
||||
}
|
||||
</pre>
|
||||
@ -579,8 +579,8 @@ entry:
|
||||
|
||||
define double @bar(double %a) {
|
||||
entry:
|
||||
%calltmp = call double @foo( double %a, double 4.000000e+00 )
|
||||
%calltmp1 = call double @bar( double 3.133700e+04 )
|
||||
%calltmp = call double @foo(double %a, double 4.000000e+00)
|
||||
%calltmp1 = call double @bar(double 3.133700e+04)
|
||||
%addtmp = fadd double %calltmp, %calltmp1
|
||||
ret double %addtmp
|
||||
}
|
||||
@ -589,7 +589,7 @@ declare double @cos(double)
|
||||
|
||||
define double @""() {
|
||||
entry:
|
||||
%calltmp = call double @cos( double 1.234000e+00 )
|
||||
%calltmp = call double @cos(double 1.234000e+00)
|
||||
ret double %calltmp
|
||||
}
|
||||
</pre>
|
||||
@ -1087,7 +1087,7 @@ main ()
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-05-28 19:07:41 +0200 (Fri, 28 May 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -387,7 +387,7 @@ entry:
|
||||
ready> <b>testfunc(4, 10);</b>
|
||||
define double @""() {
|
||||
entry:
|
||||
%calltmp = call double @testfunc( double 4.000000e+00, double 1.000000e+01 )
|
||||
%calltmp = call double @testfunc(double 4.000000e+00, double 1.000000e+01)
|
||||
ret double %calltmp
|
||||
}
|
||||
|
||||
@ -426,9 +426,9 @@ ready> <b>def foo(x) sin(x)*sin(x) + cos(x)*cos(x);</b>
|
||||
Read function definition:
|
||||
define double @foo(double %x) {
|
||||
entry:
|
||||
%calltmp = call double @sin( double %x )
|
||||
%calltmp = call double @sin(double %x)
|
||||
%multmp = fmul double %calltmp, %calltmp
|
||||
%calltmp2 = call double @cos( double %x )
|
||||
%calltmp2 = call double @cos(double %x)
|
||||
%multmp4 = fmul double %calltmp2, %calltmp2
|
||||
%addtmp = fadd double %multmp, %multmp4
|
||||
ret double %addtmp
|
||||
@ -1023,7 +1023,7 @@ extern double putchard(double X) {
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-05-28 19:07:41 +0200 (Fri, 28 May 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -651,7 +651,7 @@ entry:
|
||||
loop: ; preds = %loop, %entry
|
||||
%i = phi double [ 1.000000e+00, %entry ], [ %nextvar, %loop ]
|
||||
; body
|
||||
%calltmp = call double @putchard( double 4.200000e+01 )
|
||||
%calltmp = call double @putchard(double 4.200000e+01)
|
||||
; increment
|
||||
%nextvar = fadd double %i, 1.000000e+00
|
||||
|
||||
@ -1563,7 +1563,7 @@ operators</a>
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-05-28 19:07:41 +0200 (Fri, 28 May 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -512,7 +512,7 @@ def unary!(v)
|
||||
def unary-(v)
|
||||
0-v;
|
||||
|
||||
# Define > with the same precedence as >.
|
||||
# Define > with the same precedence as <.
|
||||
def binary> 10 (LHS RHS)
|
||||
RHS < LHS;
|
||||
|
||||
@ -1568,7 +1568,7 @@ SSA construction</a>
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-06-21 22:31:30 +0200 (Mon, 21 Jun 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -582,10 +582,10 @@ then: ; preds = %entry
|
||||
else: ; preds = %entry
|
||||
<b>%x3 = load double* %x1</b>
|
||||
%subtmp = fsub double %x3, 1.000000e+00
|
||||
%calltmp = call double @fib( double %subtmp )
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
<b>%x4 = load double* %x1</b>
|
||||
%subtmp5 = fsub double %x4, 2.000000e+00
|
||||
%calltmp6 = call double @fib( double %subtmp5 )
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
br label %ifcont
|
||||
|
||||
@ -620,9 +620,9 @@ then:
|
||||
|
||||
else:
|
||||
%subtmp = fsub double <b>%x</b>, 1.000000e+00
|
||||
%calltmp = call double @fib( double %subtmp )
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
%subtmp5 = fsub double <b>%x</b>, 2.000000e+00
|
||||
%calltmp6 = call double @fib( double %subtmp5 )
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
br label %ifcont
|
||||
|
||||
@ -650,9 +650,9 @@ entry:
|
||||
|
||||
else:
|
||||
%subtmp = fsub double %x, 1.000000e+00
|
||||
%calltmp = call double @fib( double %subtmp )
|
||||
%calltmp = call double @fib(double %subtmp)
|
||||
%subtmp5 = fsub double %x, 2.000000e+00
|
||||
%calltmp6 = call double @fib( double %subtmp5 )
|
||||
%calltmp6 = call double @fib(double %subtmp5)
|
||||
%addtmp = fadd double %calltmp, %calltmp6
|
||||
ret double %addtmp
|
||||
|
||||
@ -1901,7 +1901,7 @@ extern double printd(double X) {
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
<a href="mailto:idadesub@users.sourceforge.net">Erick Tryzelaar</a><br>
|
||||
Last modified: $Date: 2010-05-07 02:28:04 +0200 (Fri, 07 May 2010) $
|
||||
Last modified: $Date: 2010-05-28 19:07:41 +0200 (Fri, 28 May 2010) $
|
||||
</address>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1574,7 +1574,7 @@ class OurCppRunException : public std::runtime_error {
|
||||
));
|
||||
}
|
||||
|
||||
~OurCppRunException (void) throw () {};
|
||||
~OurCppRunException (void) throw () {}
|
||||
};
|
||||
|
||||
|
||||
|
@ -367,9 +367,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -400,7 +400,7 @@ Value *CallExprAST::Codegen() {
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
@ -374,9 +374,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -407,7 +407,7 @@ Value *CallExprAST::Codegen() {
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
@ -475,9 +475,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -615,7 +615,7 @@ Value *ForExprAST::Codegen() {
|
||||
StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
|
||||
}
|
||||
|
||||
Value *NextVar = Builder.CreateAdd(Variable, StepVal, "nextvar");
|
||||
Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar");
|
||||
|
||||
// Compute the end condition.
|
||||
Value *EndCond = End->Codegen();
|
||||
@ -652,7 +652,7 @@ Value *ForExprAST::Codegen() {
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
@ -571,9 +571,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -719,7 +719,7 @@ Value *ForExprAST::Codegen() {
|
||||
StepVal = ConstantFP::get(getGlobalContext(), APFloat(1.0));
|
||||
}
|
||||
|
||||
Value *NextVar = Builder.CreateAdd(Variable, StepVal, "nextvar");
|
||||
Value *NextVar = Builder.CreateFAdd(Variable, StepVal, "nextvar");
|
||||
|
||||
// Compute the end condition.
|
||||
Value *EndCond = End->Codegen();
|
||||
@ -756,7 +756,7 @@ Value *ForExprAST::Codegen() {
|
||||
|
||||
Function *PrototypeAST::Codegen() {
|
||||
// Make the function type: double(double,double) etc.
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
std::vector<const Type*> Doubles(Args.size(),
|
||||
Type::getDoubleTy(getGlobalContext()));
|
||||
FunctionType *FT = FunctionType::get(Type::getDoubleTy(getGlobalContext()),
|
||||
Doubles, false);
|
||||
|
@ -667,9 +667,9 @@ Value *BinaryExprAST::Codegen() {
|
||||
if (L == 0 || R == 0) return 0;
|
||||
|
||||
switch (Op) {
|
||||
case '+': return Builder.CreateAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateMul(L, R, "multmp");
|
||||
case '+': return Builder.CreateFAdd(L, R, "addtmp");
|
||||
case '-': return Builder.CreateFSub(L, R, "subtmp");
|
||||
case '*': return Builder.CreateFMul(L, R, "multmp");
|
||||
case '<':
|
||||
L = Builder.CreateFCmpULT(L, R, "cmptmp");
|
||||
// Convert bool 0/1 to double 0.0 or 1.0
|
||||
@ -828,7 +828,7 @@ Value *ForExprAST::Codegen() {
|
||||
// Reload, increment, and restore the alloca. This handles the case where
|
||||
// the body of the loop mutates the variable.
|
||||
Value *CurVar = Builder.CreateLoad(Alloca, VarName.c_str());
|
||||
Value *NextVar = Builder.CreateAdd(CurVar, StepVal, "nextvar");
|
||||
Value *NextVar = Builder.CreateFAdd(CurVar, StepVal, "nextvar");
|
||||
Builder.CreateStore(NextVar, Alloca);
|
||||
|
||||
// Convert condition to a bool by comparing equal to 0.0.
|
||||
|
@ -22,9 +22,9 @@ let rec codegen_expr = function
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '+' -> build_fadd lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_fsub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_fmul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
|
@ -22,9 +22,9 @@ let rec codegen_expr = function
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '+' -> build_fadd lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_fsub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_fmul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
|
@ -31,9 +31,9 @@ let rec codegen_expr = function
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '+' -> build_fadd lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_fsub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_fmul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
|
@ -60,9 +60,9 @@ let rec codegen_expr = function
|
||||
let rhs_val = codegen_expr rhs in
|
||||
begin
|
||||
match op with
|
||||
| '+' -> build_add lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_sub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_mul lhs_val rhs_val "multmp" builder
|
||||
| '+' -> build_fadd lhs_val rhs_val "addtmp" builder
|
||||
| '-' -> build_fsub lhs_val rhs_val "subtmp" builder
|
||||
| '*' -> build_fmul lhs_val rhs_val "multmp" builder
|
||||
| '<' ->
|
||||
(* Convert bool 0/1 to double 0.0 or 1.0 *)
|
||||
let i = build_fcmp Fcmp.Ult lhs_val rhs_val "cmptmp" builder in
|
||||
|
@ -226,7 +226,8 @@ typedef enum {
|
||||
LLVMExternalWeakLinkage,/**< ExternalWeak linkage description */
|
||||
LLVMGhostLinkage, /**< Obsolete */
|
||||
LLVMCommonLinkage, /**< Tentative definitions */
|
||||
LLVMLinkerPrivateLinkage /**< Like Private, but linker removes. */
|
||||
LLVMLinkerPrivateLinkage, /**< Like Private, but linker removes. */
|
||||
LLVMLinkerPrivateWeakLinkage /**< Like LinkerPrivate, but is weak. */
|
||||
} LLVMLinkage;
|
||||
|
||||
typedef enum {
|
||||
|
@ -32,7 +32,8 @@ typedef struct LLVMOpaqueTargetData *LLVMTargetDataRef;
|
||||
typedef struct LLVMStructLayout *LLVMStructLayoutRef;
|
||||
|
||||
/* Declare all of the target-initialization functions that are available. */
|
||||
#define LLVM_TARGET(TargetName) void LLVMInitialize##TargetName##TargetInfo(void);
|
||||
#define LLVM_TARGET(TargetName) \
|
||||
void LLVMInitialize##TargetName##TargetInfo(void);
|
||||
#include "llvm/Config/Targets.def"
|
||||
#undef LLVM_TARGET /* Explicit undef to make SWIG happier */
|
||||
|
||||
|
@ -102,7 +102,7 @@ lto_module_is_object_file_in_memory(const void* mem, size_t length);
|
||||
*/
|
||||
extern bool
|
||||
lto_module_is_object_file_in_memory_for_target(const void* mem, size_t length,
|
||||
const char* target_triple_prefix);
|
||||
const char* target_triple_prefix);
|
||||
|
||||
|
||||
/**
|
||||
|
75
include/llvm/ADT/DAGDeltaAlgorithm.h
Normal file
75
include/llvm/ADT/DAGDeltaAlgorithm.h
Normal file
@ -0,0 +1,75 @@
|
||||
//===--- DAGDeltaAlgorithm.h - A DAG Minimization Algorithm ----*- C++ -*--===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ADT_DAGDELTAALGORITHM_H
|
||||
#define LLVM_ADT_DAGDELTAALGORITHM_H
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// DAGDeltaAlgorithm - Implements a "delta debugging" algorithm for minimizing
|
||||
/// directed acyclic graphs using a predicate function.
|
||||
///
|
||||
/// The result of the algorithm is a subset of the input change set which is
|
||||
/// guaranteed to satisfy the predicate, assuming that the input set did. For
|
||||
/// well formed predicates, the result set is guaranteed to be such that
|
||||
/// removing any single element not required by the dependencies on the other
|
||||
/// elements would falsify the predicate.
|
||||
///
|
||||
/// The DAG should be used to represent dependencies in the changes which are
|
||||
/// likely to hold across the predicate function. That is, for a particular
|
||||
/// changeset S and predicate P:
|
||||
///
|
||||
/// P(S) => P(S union pred(S))
|
||||
///
|
||||
/// The minization algorithm uses this dependency information to attempt to
|
||||
/// eagerly prune large subsets of changes. As with \see DeltaAlgorithm, the DAG
|
||||
/// is not required to satisfy this property, but the algorithm will run
|
||||
/// substantially fewer tests with appropriate dependencies. \see DeltaAlgorithm
|
||||
/// for more information on the properties which the predicate function itself
|
||||
/// should satisfy.
|
||||
class DAGDeltaAlgorithm {
|
||||
public:
|
||||
typedef unsigned change_ty;
|
||||
typedef std::pair<change_ty, change_ty> edge_ty;
|
||||
|
||||
// FIXME: Use a decent data structure.
|
||||
typedef std::set<change_ty> changeset_ty;
|
||||
typedef std::vector<changeset_ty> changesetlist_ty;
|
||||
|
||||
public:
|
||||
virtual ~DAGDeltaAlgorithm() {}
|
||||
|
||||
/// Run - Minimize the DAG formed by the \arg Changes vertices and the \arg
|
||||
/// Dependencies edges by executing \see ExecuteOneTest() on subsets of
|
||||
/// changes and returning the smallest set which still satisfies the test
|
||||
/// predicate and the input \arg Dependencies.
|
||||
///
|
||||
/// \param Changes The list of changes.
|
||||
///
|
||||
/// \param Dependencies The list of dependencies amongst changes. For each
|
||||
/// (x,y) in \arg Dependencies, both x and y must be in \arg Changes. The
|
||||
/// minimization algorithm guarantees that for each tested changed set S, x
|
||||
/// \in S implies y \in S. It is an error to have cyclic dependencies.
|
||||
changeset_ty Run(const changeset_ty &Changes,
|
||||
const std::vector<edge_ty> &Dependencies);
|
||||
|
||||
/// UpdatedSearchState - Callback used when the search state changes.
|
||||
virtual void UpdatedSearchState(const changeset_ty &Changes,
|
||||
const changesetlist_ty &Sets,
|
||||
const changeset_ty &Required) {}
|
||||
|
||||
/// ExecuteOneTest - Execute a single test predicate on the change set \arg S.
|
||||
virtual bool ExecuteOneTest(const changeset_ty &S) = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -22,6 +22,7 @@
|
||||
#include <new>
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
|
||||
namespace llvm {
|
||||
|
@ -169,7 +169,7 @@ class EquivalenceClasses {
|
||||
/// getOrInsertLeaderValue - Return the leader for the specified value that is
|
||||
/// in the set. If the member is not in the set, it is inserted, then
|
||||
/// returned.
|
||||
const ElemTy &getOrInsertLeaderValue(const ElemTy &V) const {
|
||||
const ElemTy &getOrInsertLeaderValue(const ElemTy &V) {
|
||||
member_iterator MI = findLeader(insert(V));
|
||||
assert(MI != member_end() && "Value is not in the set!");
|
||||
return *MI;
|
||||
|
@ -166,6 +166,14 @@ class FoldingSetImpl {
|
||||
/// FindNodeOrInsertPos.
|
||||
void InsertNode(Node *N, void *InsertPos);
|
||||
|
||||
/// InsertNode - Insert the specified node into the folding set, knowing that
|
||||
/// it is not already in the folding set.
|
||||
void InsertNode(Node *N) {
|
||||
Node *Inserted = GetOrInsertNode(N);
|
||||
(void)Inserted;
|
||||
assert(Inserted == N && "Node already inserted!");
|
||||
}
|
||||
|
||||
/// size - Returns the number of nodes in the folding set.
|
||||
unsigned size() const { return NumNodes; }
|
||||
|
||||
@ -196,6 +204,10 @@ class FoldingSetImpl {
|
||||
template<typename T> struct FoldingSetTrait {
|
||||
static inline void Profile(const T& X, FoldingSetNodeID& ID) { X.Profile(ID);}
|
||||
static inline void Profile(T& X, FoldingSetNodeID& ID) { X.Profile(ID); }
|
||||
template <typename Ctx>
|
||||
static inline void Profile(T &X, FoldingSetNodeID &ID, Ctx Context) {
|
||||
X.Profile(ID, Context);
|
||||
}
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -321,6 +333,77 @@ template<class T> class FoldingSet : public FoldingSetImpl {
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// ContextualFoldingSet - This template class is a further refinement
|
||||
/// of FoldingSet which provides a context argument when calling
|
||||
/// Profile on its nodes. Currently, that argument is fixed at
|
||||
/// initialization time.
|
||||
///
|
||||
/// T must be a subclass of FoldingSetNode and implement a Profile
|
||||
/// function with signature
|
||||
/// void Profile(llvm::FoldingSetNodeID &, Ctx);
|
||||
template <class T, class Ctx>
|
||||
class ContextualFoldingSet : public FoldingSetImpl {
|
||||
// Unfortunately, this can't derive from FoldingSet<T> because the
|
||||
// construction vtable for FoldingSet<T> requires
|
||||
// FoldingSet<T>::GetNodeProfile to be instantiated, which in turn
|
||||
// requires a single-argument T::Profile().
|
||||
|
||||
private:
|
||||
Ctx Context;
|
||||
|
||||
/// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a
|
||||
/// way to convert nodes into a unique specifier.
|
||||
virtual void GetNodeProfile(FoldingSetNodeID &ID,
|
||||
FoldingSetImpl::Node *N) const {
|
||||
T *TN = static_cast<T *>(N);
|
||||
|
||||
// We must use explicit template arguments in case Ctx is a
|
||||
// reference type.
|
||||
FoldingSetTrait<T>::template Profile<Ctx>(*TN, ID, Context);
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ContextualFoldingSet(Ctx Context, unsigned Log2InitSize = 6)
|
||||
: FoldingSetImpl(Log2InitSize), Context(Context)
|
||||
{}
|
||||
|
||||
Ctx getContext() const { return Context; }
|
||||
|
||||
|
||||
typedef FoldingSetIterator<T> iterator;
|
||||
iterator begin() { return iterator(Buckets); }
|
||||
iterator end() { return iterator(Buckets+NumBuckets); }
|
||||
|
||||
typedef FoldingSetIterator<const T> const_iterator;
|
||||
const_iterator begin() const { return const_iterator(Buckets); }
|
||||
const_iterator end() const { return const_iterator(Buckets+NumBuckets); }
|
||||
|
||||
typedef FoldingSetBucketIterator<T> bucket_iterator;
|
||||
|
||||
bucket_iterator bucket_begin(unsigned hash) {
|
||||
return bucket_iterator(Buckets + (hash & (NumBuckets-1)));
|
||||
}
|
||||
|
||||
bucket_iterator bucket_end(unsigned hash) {
|
||||
return bucket_iterator(Buckets + (hash & (NumBuckets-1)), true);
|
||||
}
|
||||
|
||||
/// GetOrInsertNode - If there is an existing simple Node exactly
|
||||
/// equal to the specified node, return it. Otherwise, insert 'N'
|
||||
/// and return it instead.
|
||||
T *GetOrInsertNode(Node *N) {
|
||||
return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N));
|
||||
}
|
||||
|
||||
/// FindNodeOrInsertPos - Look up the node specified by ID. If it
|
||||
/// exists, return it. If not, return the insertion token that will
|
||||
/// make insertion faster.
|
||||
T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) {
|
||||
return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos));
|
||||
}
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// FoldingSetIteratorImpl - This is the common iterator support shared by all
|
||||
/// folding sets, which knows how to walk the folding set hash table.
|
||||
|
@ -125,9 +125,11 @@ class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> {
|
||||
key_type_ref KCurrent = ImutInfo::KeyOfValue(this->Value(T));
|
||||
|
||||
if (ImutInfo::isLess(K, KCurrent))
|
||||
return this->Balance(Add_internal(V, this->Left(T)), this->Value(T), this->Right(T));
|
||||
return this->Balance(Add_internal(V, this->Left(T)), this->Value(T),
|
||||
this->Right(T));
|
||||
else
|
||||
return this->Balance(this->Left(T), this->Value(T), Add_internal(V, this->Right(T)));
|
||||
return this->Balance(this->Left(T), this->Value(T),
|
||||
Add_internal(V, this->Right(T)));
|
||||
}
|
||||
|
||||
// Remove all overlaps from T.
|
||||
@ -150,9 +152,11 @@ class ImutIntervalAVLFactory : public ImutAVLFactory<ImutInfo> {
|
||||
|
||||
// If current key does not overlap the inserted key.
|
||||
if (CurrentK.getStart() > K.getEnd())
|
||||
return this->Balance(RemoveOverlap(this->Left(T), K, Changed), this->Value(T), this->Right(T));
|
||||
return this->Balance(RemoveOverlap(this->Left(T), K, Changed),
|
||||
this->Value(T), this->Right(T));
|
||||
else if (CurrentK.getEnd() < K.getStart())
|
||||
return this->Balance(this->Left(T), this->Value(T), RemoveOverlap(this->Right(T), K, Changed));
|
||||
return this->Balance(this->Left(T), this->Value(T),
|
||||
RemoveOverlap(this->Right(T), K, Changed));
|
||||
|
||||
// Current key overlaps with the inserted key.
|
||||
// Remove the current key.
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include <set>
|
||||
#include <stack>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
@ -52,21 +51,21 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
|
||||
|
||||
// VisitStack - Used to maintain the ordering. Top = current block
|
||||
// First element is basic block pointer, second is the 'next child' to visit
|
||||
std::stack<std::pair<NodeType *, ChildItTy> > VisitStack;
|
||||
std::vector<std::pair<NodeType *, ChildItTy> > VisitStack;
|
||||
|
||||
void traverseChild() {
|
||||
while (VisitStack.top().second != GT::child_end(VisitStack.top().first)) {
|
||||
NodeType *BB = *VisitStack.top().second++;
|
||||
while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) {
|
||||
NodeType *BB = *VisitStack.back().second++;
|
||||
if (!this->Visited.count(BB)) { // If the block is not visited...
|
||||
this->Visited.insert(BB);
|
||||
VisitStack.push(std::make_pair(BB, GT::child_begin(BB)));
|
||||
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline po_iterator(NodeType *BB) {
|
||||
this->Visited.insert(BB);
|
||||
VisitStack.push(std::make_pair(BB, GT::child_begin(BB)));
|
||||
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
|
||||
traverseChild();
|
||||
}
|
||||
inline po_iterator() {} // End is when stack is empty.
|
||||
@ -75,7 +74,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
|
||||
po_iterator_storage<SetType, ExtStorage>(S) {
|
||||
if(!S.count(BB)) {
|
||||
this->Visited.insert(BB);
|
||||
VisitStack.push(std::make_pair(BB, GT::child_begin(BB)));
|
||||
VisitStack.push_back(std::make_pair(BB, GT::child_begin(BB)));
|
||||
traverseChild();
|
||||
}
|
||||
}
|
||||
@ -102,7 +101,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
|
||||
inline bool operator!=(const _Self& x) const { return !operator==(x); }
|
||||
|
||||
inline pointer operator*() const {
|
||||
return VisitStack.top().first;
|
||||
return VisitStack.back().first;
|
||||
}
|
||||
|
||||
// This is a nonstandard operator-> that dereferences the pointer an extra
|
||||
@ -112,7 +111,7 @@ class po_iterator : public std::iterator<std::forward_iterator_tag,
|
||||
inline NodeType *operator->() const { return operator*(); }
|
||||
|
||||
inline _Self& operator++() { // Preincrement
|
||||
VisitStack.pop();
|
||||
VisitStack.pop_back();
|
||||
if (!VisitStack.empty())
|
||||
traverseChild();
|
||||
return *this;
|
||||
|
@ -143,6 +143,14 @@ class SetVector {
|
||||
vector_.pop_back();
|
||||
}
|
||||
|
||||
bool operator==(const SetVector &that) const {
|
||||
return vector_ == that.vector_;
|
||||
}
|
||||
|
||||
bool operator!=(const SetVector &that) const {
|
||||
return vector_ != that.vector_;
|
||||
}
|
||||
|
||||
private:
|
||||
set_type set_; ///< The set.
|
||||
vector_type vector_; ///< The vector.
|
||||
|
@ -46,8 +46,10 @@ class SmallPtrSetIteratorImpl;
|
||||
class SmallPtrSetImpl {
|
||||
friend class SmallPtrSetIteratorImpl;
|
||||
protected:
|
||||
/// CurArray - This is the current set of buckets. If it points to
|
||||
/// SmallArray, then the set is in 'small mode'.
|
||||
/// SmallArray - Points to a fixed size set of buckets, used in 'small mode'.
|
||||
const void **SmallArray;
|
||||
/// CurArray - This is the current set of buckets. If equal to SmallArray,
|
||||
/// then the set is in 'small mode'.
|
||||
const void **CurArray;
|
||||
/// CurArraySize - The allocated size of CurArray, always a power of two.
|
||||
/// Note that CurArray points to an array that has CurArraySize+1 elements in
|
||||
@ -57,15 +59,13 @@ class SmallPtrSetImpl {
|
||||
// If small, this is # elts allocated consequtively
|
||||
unsigned NumElements;
|
||||
unsigned NumTombstones;
|
||||
const void *SmallArray[1]; // Must be last ivar.
|
||||
|
||||
// Helper to copy construct a SmallPtrSet.
|
||||
SmallPtrSetImpl(const SmallPtrSetImpl& that);
|
||||
explicit SmallPtrSetImpl(unsigned SmallSize) {
|
||||
SmallPtrSetImpl(const void **SmallStorage, const SmallPtrSetImpl& that);
|
||||
explicit SmallPtrSetImpl(const void **SmallStorage, unsigned SmallSize) :
|
||||
SmallArray(SmallStorage), CurArray(SmallStorage), CurArraySize(SmallSize) {
|
||||
assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 &&
|
||||
"Initial size must be a power of two!");
|
||||
CurArray = &SmallArray[0];
|
||||
CurArraySize = SmallSize;
|
||||
// The end pointer, always valid, is set to a valid element to help the
|
||||
// iterator.
|
||||
CurArray[SmallSize] = 0;
|
||||
@ -123,7 +123,7 @@ class SmallPtrSetImpl {
|
||||
}
|
||||
|
||||
private:
|
||||
bool isSmall() const { return CurArray == &SmallArray[0]; }
|
||||
bool isSmall() const { return CurArray == SmallArray; }
|
||||
|
||||
unsigned Hash(const void *Ptr) const {
|
||||
return static_cast<unsigned>(((uintptr_t)Ptr >> 4) & (CurArraySize-1));
|
||||
@ -199,29 +199,29 @@ class SmallPtrSetIterator : public SmallPtrSetIteratorImpl {
|
||||
}
|
||||
};
|
||||
|
||||
/// NextPowerOfTwo - This is a helper template that rounds N up to the next
|
||||
/// power of two.
|
||||
/// RoundUpToPowerOfTwo - This is a helper template that rounds N up to the next
|
||||
/// power of two (which means N itself if N is already a power of two).
|
||||
template<unsigned N>
|
||||
struct NextPowerOfTwo;
|
||||
struct RoundUpToPowerOfTwo;
|
||||
|
||||
/// NextPowerOfTwoH - If N is not a power of two, increase it. This is a helper
|
||||
/// template used to implement NextPowerOfTwo.
|
||||
/// RoundUpToPowerOfTwoH - If N is not a power of two, increase it. This is a
|
||||
/// helper template used to implement RoundUpToPowerOfTwo.
|
||||
template<unsigned N, bool isPowerTwo>
|
||||
struct NextPowerOfTwoH {
|
||||
struct RoundUpToPowerOfTwoH {
|
||||
enum { Val = N };
|
||||
};
|
||||
template<unsigned N>
|
||||
struct NextPowerOfTwoH<N, false> {
|
||||
struct RoundUpToPowerOfTwoH<N, false> {
|
||||
enum {
|
||||
// We could just use NextVal = N+1, but this converges faster. N|(N-1) sets
|
||||
// the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111.
|
||||
Val = NextPowerOfTwo<(N|(N-1)) + 1>::Val
|
||||
Val = RoundUpToPowerOfTwo<(N|(N-1)) + 1>::Val
|
||||
};
|
||||
};
|
||||
|
||||
template<unsigned N>
|
||||
struct NextPowerOfTwo {
|
||||
enum { Val = NextPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
|
||||
struct RoundUpToPowerOfTwo {
|
||||
enum { Val = RoundUpToPowerOfTwoH<N, (N&(N-1)) == 0>::Val };
|
||||
};
|
||||
|
||||
|
||||
@ -232,16 +232,17 @@ struct NextPowerOfTwo {
|
||||
template<class PtrType, unsigned SmallSize>
|
||||
class SmallPtrSet : public SmallPtrSetImpl {
|
||||
// Make sure that SmallSize is a power of two, round up if not.
|
||||
enum { SmallSizePowTwo = NextPowerOfTwo<SmallSize>::Val };
|
||||
void *SmallArray[SmallSizePowTwo];
|
||||
enum { SmallSizePowTwo = RoundUpToPowerOfTwo<SmallSize>::Val };
|
||||
/// SmallStorage - Fixed size storage used in 'small mode'. The extra element
|
||||
/// ensures that the end iterator actually points to valid memory.
|
||||
const void *SmallStorage[SmallSizePowTwo+1];
|
||||
typedef PointerLikeTypeTraits<PtrType> PtrTraits;
|
||||
public:
|
||||
SmallPtrSet() : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {}
|
||||
SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(that) {}
|
||||
SmallPtrSet() : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {}
|
||||
SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(SmallStorage, that) {}
|
||||
|
||||
template<typename It>
|
||||
SmallPtrSet(It I, It E)
|
||||
: SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {
|
||||
SmallPtrSet(It I, It E) : SmallPtrSetImpl(SmallStorage, SmallSizePowTwo) {
|
||||
insert(I, E);
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "llvm/Support/type_traits.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
@ -70,35 +72,35 @@ class SmallVectorBase {
|
||||
#endif
|
||||
} FirstEl;
|
||||
// Space after 'FirstEl' is clobbered, do not add any instance vars after it.
|
||||
|
||||
|
||||
protected:
|
||||
SmallVectorBase(size_t Size)
|
||||
: BeginX(&FirstEl), EndX(&FirstEl), CapacityX((char*)&FirstEl+Size) {}
|
||||
|
||||
|
||||
/// isSmall - Return true if this is a smallvector which has not had dynamic
|
||||
/// memory allocated for it.
|
||||
bool isSmall() const {
|
||||
return BeginX == static_cast<const void*>(&FirstEl);
|
||||
}
|
||||
|
||||
|
||||
/// size_in_bytes - This returns size()*sizeof(T).
|
||||
size_t size_in_bytes() const {
|
||||
return size_t((char*)EndX - (char*)BeginX);
|
||||
}
|
||||
|
||||
|
||||
/// capacity_in_bytes - This returns capacity()*sizeof(T).
|
||||
size_t capacity_in_bytes() const {
|
||||
return size_t((char*)CapacityX - (char*)BeginX);
|
||||
}
|
||||
|
||||
|
||||
/// grow_pod - This is an implementation of the grow() method which only works
|
||||
/// on POD-like datatypes and is out of line to reduce code duplication.
|
||||
void grow_pod(size_t MinSizeInBytes, size_t TSize);
|
||||
|
||||
|
||||
public:
|
||||
bool empty() const { return BeginX == EndX; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
class SmallVectorTemplateCommon : public SmallVectorBase {
|
||||
@ -106,21 +108,21 @@ class SmallVectorTemplateCommon : public SmallVectorBase {
|
||||
void setEnd(T *P) { this->EndX = P; }
|
||||
public:
|
||||
SmallVectorTemplateCommon(size_t Size) : SmallVectorBase(Size) {}
|
||||
|
||||
|
||||
typedef size_t size_type;
|
||||
typedef ptrdiff_t difference_type;
|
||||
typedef T value_type;
|
||||
typedef T *iterator;
|
||||
typedef const T *const_iterator;
|
||||
|
||||
|
||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||
|
||||
|
||||
typedef T &reference;
|
||||
typedef const T &const_reference;
|
||||
typedef T *pointer;
|
||||
typedef const T *const_pointer;
|
||||
|
||||
|
||||
// forward iterator creation methods.
|
||||
iterator begin() { return (iterator)this->BeginX; }
|
||||
const_iterator begin() const { return (const_iterator)this->BeginX; }
|
||||
@ -130,7 +132,7 @@ class SmallVectorTemplateCommon : public SmallVectorBase {
|
||||
iterator capacity_ptr() { return (iterator)this->CapacityX; }
|
||||
const_iterator capacity_ptr() const { return (const_iterator)this->CapacityX;}
|
||||
public:
|
||||
|
||||
|
||||
// reverse iterator creation methods.
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); }
|
||||
@ -139,16 +141,16 @@ class SmallVectorTemplateCommon : public SmallVectorBase {
|
||||
|
||||
size_type size() const { return end()-begin(); }
|
||||
size_type max_size() const { return size_type(-1) / sizeof(T); }
|
||||
|
||||
|
||||
/// capacity - Return the total number of elements in the currently allocated
|
||||
/// buffer.
|
||||
size_t capacity() const { return capacity_ptr() - begin(); }
|
||||
|
||||
|
||||
/// data - Return a pointer to the vector's buffer, even if empty().
|
||||
pointer data() { return pointer(begin()); }
|
||||
/// data - Return a pointer to the vector's buffer, even if empty().
|
||||
const_pointer data() const { return const_pointer(begin()); }
|
||||
|
||||
|
||||
reference operator[](unsigned idx) {
|
||||
assert(begin() + idx < end());
|
||||
return begin()[idx];
|
||||
@ -172,7 +174,7 @@ class SmallVectorTemplateCommon : public SmallVectorBase {
|
||||
return end()[-1];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// SmallVectorTemplateBase<isPodLike = false> - This is where we put method
|
||||
/// implementations that are designed to work with non-POD-like T's.
|
||||
template <typename T, bool isPodLike>
|
||||
@ -186,14 +188,14 @@ class SmallVectorTemplateBase : public SmallVectorTemplateCommon<T> {
|
||||
E->~T();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
|
||||
/// starting with "Dest", constructing elements into it as needed.
|
||||
template<typename It1, typename It2>
|
||||
static void uninitialized_copy(It1 I, It1 E, It2 Dest) {
|
||||
std::uninitialized_copy(I, E, Dest);
|
||||
}
|
||||
|
||||
|
||||
/// grow - double the size of the allocated memory, guaranteeing space for at
|
||||
/// least one more element or MinSize if specified.
|
||||
void grow(size_t MinSize = 0);
|
||||
@ -207,34 +209,34 @@ void SmallVectorTemplateBase<T, isPodLike>::grow(size_t MinSize) {
|
||||
size_t NewCapacity = 2*CurCapacity;
|
||||
if (NewCapacity < MinSize)
|
||||
NewCapacity = MinSize;
|
||||
T *NewElts = static_cast<T*>(operator new(NewCapacity*sizeof(T)));
|
||||
|
||||
T *NewElts = static_cast<T*>(malloc(NewCapacity*sizeof(T)));
|
||||
|
||||
// Copy the elements over.
|
||||
this->uninitialized_copy(this->begin(), this->end(), NewElts);
|
||||
|
||||
|
||||
// Destroy the original elements.
|
||||
destroy_range(this->begin(), this->end());
|
||||
|
||||
|
||||
// If this wasn't grown from the inline copy, deallocate the old space.
|
||||
if (!this->isSmall())
|
||||
operator delete(this->begin());
|
||||
|
||||
free(this->begin());
|
||||
|
||||
this->setEnd(NewElts+CurSize);
|
||||
this->BeginX = NewElts;
|
||||
this->CapacityX = this->begin()+NewCapacity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/// SmallVectorTemplateBase<isPodLike = true> - This is where we put method
|
||||
/// implementations that are designed to work with POD-like T's.
|
||||
template <typename T>
|
||||
class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
|
||||
public:
|
||||
SmallVectorTemplateBase(size_t Size) : SmallVectorTemplateCommon<T>(Size) {}
|
||||
|
||||
|
||||
// No need to do a destroy loop for POD's.
|
||||
static void destroy_range(T *, T *) {}
|
||||
|
||||
|
||||
/// uninitialized_copy - Copy the range [I, E) onto the uninitialized memory
|
||||
/// starting with "Dest", constructing elements into it as needed.
|
||||
template<typename It1, typename It2>
|
||||
@ -259,33 +261,35 @@ class SmallVectorTemplateBase<T, true> : public SmallVectorTemplateCommon<T> {
|
||||
this->grow_pod(MinSize*sizeof(T), sizeof(T));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// SmallVectorImpl - This class consists of common code factored out of the
|
||||
/// SmallVector class to reduce code duplication based on the SmallVector 'N'
|
||||
/// template parameter.
|
||||
template <typename T>
|
||||
class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
typedef SmallVectorTemplateBase<T, isPodLike<T>::value > SuperClass;
|
||||
|
||||
SmallVectorImpl(const SmallVectorImpl&); // DISABLED.
|
||||
public:
|
||||
typedef typename SuperClass::iterator iterator;
|
||||
typedef typename SuperClass::size_type size_type;
|
||||
|
||||
|
||||
// Default ctor - Initialize to empty.
|
||||
explicit SmallVectorImpl(unsigned N)
|
||||
: SmallVectorTemplateBase<T, isPodLike<T>::value>(N*sizeof(T)) {
|
||||
}
|
||||
|
||||
|
||||
~SmallVectorImpl() {
|
||||
// Destroy the constructed elements in the vector.
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
|
||||
|
||||
// If this wasn't grown from the inline copy, deallocate the old space.
|
||||
if (!this->isSmall())
|
||||
operator delete(this->begin());
|
||||
free(this->begin());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void clear() {
|
||||
this->destroy_range(this->begin(), this->end());
|
||||
this->EndX = this->BeginX;
|
||||
@ -319,7 +323,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
if (this->capacity() < N)
|
||||
this->grow(N);
|
||||
}
|
||||
|
||||
|
||||
void push_back(const T &Elt) {
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
@ -330,21 +334,21 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
this->grow();
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
|
||||
void pop_back() {
|
||||
this->setEnd(this->end()-1);
|
||||
this->end()->~T();
|
||||
}
|
||||
|
||||
|
||||
T pop_back_val() {
|
||||
T Result = this->back();
|
||||
pop_back();
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void swap(SmallVectorImpl &RHS);
|
||||
|
||||
|
||||
/// append - Add the specified range to the end of the SmallVector.
|
||||
///
|
||||
template<typename in_iter>
|
||||
@ -353,26 +357,26 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
// Grow allocated space if needed.
|
||||
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
|
||||
this->grow(this->size()+NumInputs);
|
||||
|
||||
|
||||
// Copy the new elements over.
|
||||
// TODO: NEED To compile time dispatch on whether in_iter is a random access
|
||||
// iterator to use the fast uninitialized_copy.
|
||||
std::uninitialized_copy(in_start, in_end, this->end());
|
||||
this->setEnd(this->end() + NumInputs);
|
||||
}
|
||||
|
||||
|
||||
/// append - Add the specified range to the end of the SmallVector.
|
||||
///
|
||||
void append(size_type NumInputs, const T &Elt) {
|
||||
// Grow allocated space if needed.
|
||||
if (NumInputs > size_type(this->capacity_ptr()-this->end()))
|
||||
this->grow(this->size()+NumInputs);
|
||||
|
||||
|
||||
// Copy the new elements over.
|
||||
std::uninitialized_fill_n(this->end(), NumInputs, Elt);
|
||||
this->setEnd(this->end() + NumInputs);
|
||||
}
|
||||
|
||||
|
||||
void assign(unsigned NumElts, const T &Elt) {
|
||||
clear();
|
||||
if (this->capacity() < NumElts)
|
||||
@ -380,7 +384,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
this->setEnd(this->begin()+NumElts);
|
||||
construct_range(this->begin(), this->end(), Elt);
|
||||
}
|
||||
|
||||
|
||||
iterator erase(iterator I) {
|
||||
iterator N = I;
|
||||
// Shift all elts down one.
|
||||
@ -389,7 +393,7 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
pop_back();
|
||||
return(N);
|
||||
}
|
||||
|
||||
|
||||
iterator erase(iterator S, iterator E) {
|
||||
iterator N = S;
|
||||
// Shift all elts down.
|
||||
@ -399,13 +403,13 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
this->setEnd(I);
|
||||
return(N);
|
||||
}
|
||||
|
||||
|
||||
iterator insert(iterator I, const T &Elt) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
push_back(Elt);
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
|
||||
if (this->EndX < this->CapacityX) {
|
||||
Retry:
|
||||
new (this->end()) T(this->back());
|
||||
@ -420,22 +424,22 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
I = this->begin()+EltNo;
|
||||
goto Retry;
|
||||
}
|
||||
|
||||
|
||||
iterator insert(iterator I, size_type NumToInsert, const T &Elt) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
append(NumToInsert, Elt);
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
|
||||
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
|
||||
size_t InsertElt = I - this->begin();
|
||||
|
||||
|
||||
// Ensure there is enough space.
|
||||
reserve(static_cast<unsigned>(this->size() + NumToInsert));
|
||||
|
||||
|
||||
// Uninvalidate the iterator.
|
||||
I = this->begin()+InsertElt;
|
||||
|
||||
|
||||
// If there are more elements between the insertion point and the end of the
|
||||
// range than there are being inserted, we can use a simple approach to
|
||||
// insertion. Since we already reserved space, we know that this won't
|
||||
@ -443,48 +447,48 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
if (size_t(this->end()-I) >= NumToInsert) {
|
||||
T *OldEnd = this->end();
|
||||
append(this->end()-NumToInsert, this->end());
|
||||
|
||||
|
||||
// Copy the existing elements that get replaced.
|
||||
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
|
||||
|
||||
|
||||
std::fill_n(I, NumToInsert, Elt);
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise, we're inserting more elements than exist already, and we're
|
||||
// not inserting at the end.
|
||||
|
||||
|
||||
// Copy over the elements that we're about to overwrite.
|
||||
T *OldEnd = this->end();
|
||||
this->setEnd(this->end() + NumToInsert);
|
||||
size_t NumOverwritten = OldEnd-I;
|
||||
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
|
||||
|
||||
|
||||
// Replace the overwritten part.
|
||||
std::fill_n(I, NumOverwritten, Elt);
|
||||
|
||||
|
||||
// Insert the non-overwritten middle part.
|
||||
std::uninitialized_fill_n(OldEnd, NumToInsert-NumOverwritten, Elt);
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
template<typename ItTy>
|
||||
iterator insert(iterator I, ItTy From, ItTy To) {
|
||||
if (I == this->end()) { // Important special case for empty vector.
|
||||
append(From, To);
|
||||
return this->end()-1;
|
||||
}
|
||||
|
||||
|
||||
size_t NumToInsert = std::distance(From, To);
|
||||
// Convert iterator to elt# to avoid invalidating iterator when we reserve()
|
||||
size_t InsertElt = I - this->begin();
|
||||
|
||||
|
||||
// Ensure there is enough space.
|
||||
reserve(static_cast<unsigned>(this->size() + NumToInsert));
|
||||
|
||||
|
||||
// Uninvalidate the iterator.
|
||||
I = this->begin()+InsertElt;
|
||||
|
||||
|
||||
// If there are more elements between the insertion point and the end of the
|
||||
// range than there are being inserted, we can use a simple approach to
|
||||
// insertion. Since we already reserved space, we know that this won't
|
||||
@ -492,37 +496,37 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
if (size_t(this->end()-I) >= NumToInsert) {
|
||||
T *OldEnd = this->end();
|
||||
append(this->end()-NumToInsert, this->end());
|
||||
|
||||
|
||||
// Copy the existing elements that get replaced.
|
||||
std::copy_backward(I, OldEnd-NumToInsert, OldEnd);
|
||||
|
||||
|
||||
std::copy(From, To, I);
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise, we're inserting more elements than exist already, and we're
|
||||
// not inserting at the end.
|
||||
|
||||
|
||||
// Copy over the elements that we're about to overwrite.
|
||||
T *OldEnd = this->end();
|
||||
this->setEnd(this->end() + NumToInsert);
|
||||
size_t NumOverwritten = OldEnd-I;
|
||||
this->uninitialized_copy(I, OldEnd, this->end()-NumOverwritten);
|
||||
|
||||
|
||||
// Replace the overwritten part.
|
||||
for (; NumOverwritten > 0; --NumOverwritten) {
|
||||
*I = *From;
|
||||
++I; ++From;
|
||||
}
|
||||
|
||||
|
||||
// Insert the non-overwritten middle part.
|
||||
this->uninitialized_copy(From, To, OldEnd);
|
||||
return I;
|
||||
}
|
||||
|
||||
|
||||
const SmallVectorImpl
|
||||
&operator=(const SmallVectorImpl &RHS);
|
||||
|
||||
|
||||
bool operator==(const SmallVectorImpl &RHS) const {
|
||||
if (this->size() != RHS.size()) return false;
|
||||
return std::equal(this->begin(), this->end(), RHS.begin());
|
||||
@ -530,12 +534,12 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
bool operator!=(const SmallVectorImpl &RHS) const {
|
||||
return !(*this == RHS);
|
||||
}
|
||||
|
||||
|
||||
bool operator<(const SmallVectorImpl &RHS) const {
|
||||
return std::lexicographical_compare(this->begin(), this->end(),
|
||||
RHS.begin(), RHS.end());
|
||||
}
|
||||
|
||||
|
||||
/// set_size - Set the array size to \arg N, which the current array must have
|
||||
/// enough capacity for.
|
||||
///
|
||||
@ -549,14 +553,14 @@ class SmallVectorImpl : public SmallVectorTemplateBase<T, isPodLike<T>::value> {
|
||||
assert(N <= this->capacity());
|
||||
this->setEnd(this->begin() + N);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
static void construct_range(T *S, T *E, const T &Elt) {
|
||||
for (; S != E; ++S)
|
||||
new (S) T(Elt);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) {
|
||||
|
@ -56,6 +56,10 @@ class Statistic {
|
||||
}
|
||||
|
||||
const Statistic &operator++() {
|
||||
// FIXME: This function and all those that follow carefully use an
|
||||
// atomic operation to update the value safely in the presence of
|
||||
// concurrent accesses, but not to read the return value, so the
|
||||
// return value is not thread safe.
|
||||
sys::AtomicIncrement(&Value);
|
||||
return init();
|
||||
}
|
||||
|
@ -100,7 +100,8 @@ class Triple {
|
||||
Psp,
|
||||
Solaris,
|
||||
Win32,
|
||||
Haiku
|
||||
Haiku,
|
||||
Minix
|
||||
};
|
||||
|
||||
private:
|
||||
@ -242,8 +243,8 @@ class Triple {
|
||||
/// environment components with a single string.
|
||||
void setOSAndEnvironmentName(StringRef Str);
|
||||
|
||||
/// getArchNameForAssembler - Get an architecture name that is understood by the
|
||||
/// target assembler.
|
||||
/// getArchNameForAssembler - Get an architecture name that is understood by
|
||||
/// the target assembler.
|
||||
const char *getArchNameForAssembler();
|
||||
|
||||
/// @}
|
||||
|
@ -59,16 +59,16 @@ struct ValueMapConfig {
|
||||
struct ExtraData {};
|
||||
|
||||
template<typename ExtraDataT>
|
||||
static void onRAUW(const ExtraDataT &Data, KeyT Old, KeyT New) {}
|
||||
static void onRAUW(const ExtraDataT & /*Data*/, KeyT /*Old*/, KeyT /*New*/) {}
|
||||
template<typename ExtraDataT>
|
||||
static void onDelete(const ExtraDataT &Data, KeyT Old) {}
|
||||
static void onDelete(const ExtraDataT &/*Data*/, KeyT /*Old*/) {}
|
||||
|
||||
/// Returns a mutex that should be acquired around any changes to the map.
|
||||
/// This is only acquired from the CallbackVH (and held around calls to onRAUW
|
||||
/// and onDelete) and not inside other ValueMap methods. NULL means that no
|
||||
/// mutex is necessary.
|
||||
template<typename ExtraDataT>
|
||||
static sys::Mutex *getMutex(const ExtraDataT &Data) { return NULL; }
|
||||
static sys::Mutex *getMutex(const ExtraDataT &/*Data*/) { return NULL; }
|
||||
};
|
||||
|
||||
/// See the file comment.
|
||||
|
@ -39,6 +39,7 @@
|
||||
#define LLVM_ADT_ILIST_H
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
|
||||
namespace llvm {
|
||||
|
@ -146,6 +146,7 @@ class PATypeHolder {
|
||||
mutable const Type *Ty;
|
||||
void destroy();
|
||||
public:
|
||||
PATypeHolder() : Ty(0) {}
|
||||
PATypeHolder(const Type *ty) : Ty(ty) {
|
||||
addRef();
|
||||
}
|
||||
@ -153,7 +154,7 @@ class PATypeHolder {
|
||||
addRef();
|
||||
}
|
||||
|
||||
~PATypeHolder() { if (Ty) dropRef(); }
|
||||
~PATypeHolder() { dropRef(); }
|
||||
|
||||
operator Type *() const { return get(); }
|
||||
Type *get() const;
|
||||
|
@ -165,27 +165,6 @@ class AliasAnalysis {
|
||||
/// ModRefInfo - Whether the pointer is loaded or stored to/from.
|
||||
///
|
||||
ModRefResult ModRefInfo;
|
||||
|
||||
/// AccessType - Specific fine-grained access information for the argument.
|
||||
/// If none of these classifications is general enough, the
|
||||
/// getModRefBehavior method should not return AccessesArguments*. If a
|
||||
/// record is not returned for a particular argument, the argument is never
|
||||
/// dead and never dereferenced.
|
||||
enum AccessType {
|
||||
/// ScalarAccess - The pointer is dereferenced.
|
||||
///
|
||||
ScalarAccess,
|
||||
|
||||
/// ArrayAccess - The pointer is indexed through as an array of elements.
|
||||
///
|
||||
ArrayAccess,
|
||||
|
||||
/// ElementAccess ?? P->F only?
|
||||
|
||||
/// CallsThrough - Indirect calls are made through the specified function
|
||||
/// pointer.
|
||||
CallsThrough
|
||||
};
|
||||
};
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given call site.
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- CFGPrinter.h - CFG printer external interface ------------*- C++ -*-===//
|
||||
//===-- CFGPrinter.h - CFG printer external interface -----------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -43,8 +43,8 @@ struct DOTGraphTraits<const Function*> : public DefaultDOTGraphTraits {
|
||||
return OS.str();
|
||||
}
|
||||
|
||||
static std::string getCompleteNodeLabel(const BasicBlock *Node,
|
||||
const Function *Graph) {
|
||||
static std::string getCompleteNodeLabel(const BasicBlock *Node,
|
||||
const Function *Graph) {
|
||||
std::string Str;
|
||||
raw_string_ostream OS(Str);
|
||||
|
||||
|
@ -21,9 +21,9 @@ namespace llvm {
|
||||
/// by the enclosing function (which is required to exist). This routine can
|
||||
/// be expensive, so consider caching the results. The boolean ReturnCaptures
|
||||
/// specifies whether returning the value (or part of it) from the function
|
||||
/// counts as capturing it or not. The boolean StoreCaptures specified whether
|
||||
/// storing the value (or part of it) into memory anywhere automatically
|
||||
/// counts as capturing it or not.
|
||||
/// counts as capturing it or not. The boolean StoreCaptures specified
|
||||
/// whether storing the value (or part of it) into memory anywhere
|
||||
/// automatically counts as capturing it or not.
|
||||
bool PointerMayBeCaptured(const Value *V,
|
||||
bool ReturnCaptures,
|
||||
bool StoreCaptures);
|
||||
|
72
include/llvm/Analysis/CodeMetrics.h
Normal file
72
include/llvm/Analysis/CodeMetrics.h
Normal file
@ -0,0 +1,72 @@
|
||||
//===- CodeMetrics.h - Measures the weight of a function---------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements various weight measurements for a function, helping
|
||||
// the Inliner and PartialSpecialization decide whether to duplicate its
|
||||
// contents.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_CODEMETRICS_H
|
||||
#define LLVM_ANALYSIS_CODEMETRICS_H
|
||||
|
||||
namespace llvm {
|
||||
// CodeMetrics - Calculate size and a few similar metrics for a set of
|
||||
// basic blocks.
|
||||
struct CodeMetrics {
|
||||
/// NeverInline - True if this callee should never be inlined into a
|
||||
/// caller.
|
||||
// bool NeverInline;
|
||||
|
||||
// True if this function contains a call to setjmp or _setjmp
|
||||
bool callsSetJmp;
|
||||
|
||||
// True if this function calls itself
|
||||
bool isRecursive;
|
||||
|
||||
// True if this function contains one or more indirect branches
|
||||
bool containsIndirectBr;
|
||||
|
||||
/// usesDynamicAlloca - True if this function calls alloca (in the C sense).
|
||||
bool usesDynamicAlloca;
|
||||
|
||||
/// NumInsts, NumBlocks - Keep track of how large each function is, which
|
||||
/// is used to estimate the code size cost of inlining it.
|
||||
unsigned NumInsts, NumBlocks;
|
||||
|
||||
/// NumBBInsts - Keeps track of basic block code size estimates.
|
||||
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
|
||||
|
||||
/// NumCalls - Keep track of the number of calls to 'big' functions.
|
||||
unsigned NumCalls;
|
||||
|
||||
/// NumVectorInsts - Keep track of how many instructions produce vector
|
||||
/// values. The inliner is being more aggressive with inlining vector
|
||||
/// kernels.
|
||||
unsigned NumVectorInsts;
|
||||
|
||||
/// NumRets - Keep track of how many Ret instructions the block contains.
|
||||
unsigned NumRets;
|
||||
|
||||
CodeMetrics() : callsSetJmp(false), isRecursive(false),
|
||||
containsIndirectBr(false), usesDynamicAlloca(false),
|
||||
NumInsts(0), NumBlocks(0), NumCalls(0), NumVectorInsts(0),
|
||||
NumRets(0) {}
|
||||
|
||||
/// analyzeBasicBlock - Add information about the specified basic block
|
||||
/// to the current structure.
|
||||
void analyzeBasicBlock(const BasicBlock *BB);
|
||||
|
||||
/// analyzeFunction - Add information about the specified function
|
||||
/// to the current structure.
|
||||
void analyzeFunction(Function *F);
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
@ -56,6 +56,7 @@ namespace llvm {
|
||||
}
|
||||
|
||||
GlobalVariable *getGlobalVariableField(unsigned Elt) const;
|
||||
Function *getFunctionField(unsigned Elt) const;
|
||||
|
||||
public:
|
||||
explicit DIDescriptor() : DbgNode(0) {}
|
||||
@ -409,6 +410,8 @@ namespace llvm {
|
||||
/// describes - Return true if this subprogram provides debugging
|
||||
/// information for the function F.
|
||||
bool describes(const Function *F);
|
||||
|
||||
Function *getFunction() const { return getFunctionField(16); }
|
||||
};
|
||||
|
||||
/// DIGlobalVariable - This is a wrapper for a global variable.
|
||||
@ -577,7 +580,8 @@ namespace llvm {
|
||||
unsigned RunTimeVer = 0);
|
||||
|
||||
/// CreateFile - Create a new descriptor for the specified file.
|
||||
DIFile CreateFile(StringRef Filename, StringRef Directory, DICompileUnit CU);
|
||||
DIFile CreateFile(StringRef Filename, StringRef Directory,
|
||||
DICompileUnit CU);
|
||||
|
||||
/// CreateEnumerator - Create a single enumerator value.
|
||||
DIEnumerator CreateEnumerator(StringRef Name, uint64_t Val);
|
||||
@ -658,7 +662,8 @@ namespace llvm {
|
||||
unsigned VIndex = 0,
|
||||
DIType = DIType(),
|
||||
bool isArtificial = 0,
|
||||
bool isOptimized = false);
|
||||
bool isOptimized = false,
|
||||
Function *Fn = 0);
|
||||
|
||||
/// CreateSubprogramDefinition - Create new subprogram descriptor for the
|
||||
/// given declaration.
|
||||
|
@ -152,8 +152,9 @@ void Compress(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
}
|
||||
|
||||
template<class GraphT>
|
||||
typename GraphT::NodeType* Eval(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType *V) {
|
||||
typename GraphT::NodeType*
|
||||
Eval(DominatorTreeBase<typename GraphT::NodeType>& DT,
|
||||
typename GraphT::NodeType *V) {
|
||||
typename DominatorTreeBase<typename GraphT::NodeType>::InfoRec &VInfo =
|
||||
DT.Info[V];
|
||||
#if !BALANCE_IDOM_TREE
|
||||
@ -265,14 +266,17 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT,
|
||||
|
||||
// initialize the semi dominator to point to the parent node
|
||||
WInfo.Semi = WInfo.Parent;
|
||||
for (typename GraphTraits<Inverse<NodeT> >::ChildIteratorType CI =
|
||||
GraphTraits<Inverse<NodeT> >::child_begin(W),
|
||||
E = GraphTraits<Inverse<NodeT> >::child_end(W); CI != E; ++CI)
|
||||
if (DT.Info.count(*CI)) { // Only if this predecessor is reachable!
|
||||
unsigned SemiU = DT.Info[Eval<GraphT>(DT, *CI)].Semi;
|
||||
typedef GraphTraits<Inverse<NodeT> > InvTraits;
|
||||
for (typename InvTraits::ChildIteratorType CI =
|
||||
InvTraits::child_begin(W),
|
||||
E = InvTraits::child_end(W); CI != E; ++CI) {
|
||||
typename InvTraits::NodeType *N = *CI;
|
||||
if (DT.Info.count(N)) { // Only if this predecessor is reachable!
|
||||
unsigned SemiU = DT.Info[Eval<GraphT>(DT, N)].Semi;
|
||||
if (SemiU < WInfo.Semi)
|
||||
WInfo.Semi = SemiU;
|
||||
}
|
||||
}
|
||||
|
||||
DT.Info[DT.Vertex[WInfo.Semi]].Bucket.push_back(W);
|
||||
|
||||
|
@ -246,22 +246,25 @@ class DominatorTreeBase : public DominatorBase<NodeT> {
|
||||
typename GraphT::NodeType* NewBBSucc = *GraphT::child_begin(NewBB);
|
||||
|
||||
std::vector<typename GraphT::NodeType*> PredBlocks;
|
||||
for (typename GraphTraits<Inverse<N> >::ChildIteratorType PI =
|
||||
GraphTraits<Inverse<N> >::child_begin(NewBB),
|
||||
PE = GraphTraits<Inverse<N> >::child_end(NewBB); PI != PE; ++PI)
|
||||
typedef GraphTraits<Inverse<N> > InvTraits;
|
||||
for (typename InvTraits::ChildIteratorType PI =
|
||||
InvTraits::child_begin(NewBB),
|
||||
PE = InvTraits::child_end(NewBB); PI != PE; ++PI)
|
||||
PredBlocks.push_back(*PI);
|
||||
|
||||
assert(!PredBlocks.empty() && "No predblocks??");
|
||||
assert(!PredBlocks.empty() && "No predblocks?");
|
||||
|
||||
bool NewBBDominatesNewBBSucc = true;
|
||||
for (typename GraphTraits<Inverse<N> >::ChildIteratorType PI =
|
||||
GraphTraits<Inverse<N> >::child_begin(NewBBSucc),
|
||||
E = GraphTraits<Inverse<N> >::child_end(NewBBSucc); PI != E; ++PI)
|
||||
if (*PI != NewBB && !DT.dominates(NewBBSucc, *PI) &&
|
||||
DT.isReachableFromEntry(*PI)) {
|
||||
for (typename InvTraits::ChildIteratorType PI =
|
||||
InvTraits::child_begin(NewBBSucc),
|
||||
E = InvTraits::child_end(NewBBSucc); PI != E; ++PI) {
|
||||
typename InvTraits::NodeType *ND = *PI;
|
||||
if (ND != NewBB && !DT.dominates(NewBBSucc, ND) &&
|
||||
DT.isReachableFromEntry(ND)) {
|
||||
NewBBDominatesNewBBSucc = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Find NewBB's immediate dominator and create new dominator tree node for
|
||||
// NewBB.
|
||||
@ -704,7 +707,6 @@ class DominatorTree : public FunctionPass {
|
||||
}
|
||||
|
||||
~DominatorTree() {
|
||||
DT->releaseMemory();
|
||||
delete DT;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <vector>
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/ADT/ValueMap.h"
|
||||
#include "llvm/Analysis/CodeMetrics.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -29,46 +30,6 @@ namespace llvm {
|
||||
template<class PtrType, unsigned SmallSize>
|
||||
class SmallPtrSet;
|
||||
|
||||
// CodeMetrics - Calculate size and a few similar metrics for a set of
|
||||
// basic blocks.
|
||||
struct CodeMetrics {
|
||||
/// NeverInline - True if this callee should never be inlined into a
|
||||
/// caller.
|
||||
bool NeverInline;
|
||||
|
||||
/// usesDynamicAlloca - True if this function calls alloca (in the C sense).
|
||||
bool usesDynamicAlloca;
|
||||
|
||||
/// NumInsts, NumBlocks - Keep track of how large each function is, which
|
||||
/// is used to estimate the code size cost of inlining it.
|
||||
unsigned NumInsts, NumBlocks;
|
||||
|
||||
/// NumBBInsts - Keeps track of basic block code size estimates.
|
||||
DenseMap<const BasicBlock *, unsigned> NumBBInsts;
|
||||
|
||||
/// NumCalls - Keep track of the number of calls to 'big' functions.
|
||||
unsigned NumCalls;
|
||||
|
||||
/// NumVectorInsts - Keep track of how many instructions produce vector
|
||||
/// values. The inliner is being more aggressive with inlining vector
|
||||
/// kernels.
|
||||
unsigned NumVectorInsts;
|
||||
|
||||
/// NumRets - Keep track of how many Ret instructions the block contains.
|
||||
unsigned NumRets;
|
||||
|
||||
CodeMetrics() : NeverInline(false), usesDynamicAlloca(false), NumInsts(0),
|
||||
NumBlocks(0), NumCalls(0), NumVectorInsts(0), NumRets(0) {}
|
||||
|
||||
/// analyzeBasicBlock - Add information about the specified basic block
|
||||
/// to the current structure.
|
||||
void analyzeBasicBlock(const BasicBlock *BB);
|
||||
|
||||
/// analyzeFunction - Add information about the specified function
|
||||
/// to the current structure.
|
||||
void analyzeFunction(Function *F);
|
||||
};
|
||||
|
||||
namespace InlineConstants {
|
||||
// Various magic constants used to adjust heuristics.
|
||||
const int InstrCost = 5;
|
||||
@ -163,6 +124,10 @@ namespace llvm {
|
||||
/// analyzeFunction - Add information about the specified function
|
||||
/// to the current structure.
|
||||
void analyzeFunction(Function *F);
|
||||
|
||||
/// NeverInline - Returns true if the function should never be
|
||||
/// inlined into any caller.
|
||||
bool NeverInline();
|
||||
};
|
||||
|
||||
// The Function* for a function can be changed (by ArgumentPromotion);
|
||||
|
@ -36,9 +36,9 @@
|
||||
#include "llvm/Analysis/IntervalPartition.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Support/CFG.h"
|
||||
#include <stack>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -88,7 +88,7 @@ inline void addNodeToInterval(Interval *Int, Interval *I) {
|
||||
template<class NodeTy, class OrigContainer_t, class GT = GraphTraits<NodeTy*>,
|
||||
class IGT = GraphTraits<Inverse<NodeTy*> > >
|
||||
class IntervalIterator {
|
||||
std::stack<std::pair<Interval*, typename Interval::succ_iterator> > IntStack;
|
||||
std::vector<std::pair<Interval*, typename Interval::succ_iterator> > IntStack;
|
||||
std::set<BasicBlock*> Visited;
|
||||
OrigContainer_t *OrigContainer;
|
||||
bool IOwnMem; // If True, delete intervals when done with them
|
||||
@ -116,15 +116,15 @@ class IntervalIterator {
|
||||
if (IOwnMem)
|
||||
while (!IntStack.empty()) {
|
||||
delete operator*();
|
||||
IntStack.pop();
|
||||
IntStack.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;}
|
||||
inline bool operator!=(const _Self& x) const { return !operator==(x); }
|
||||
|
||||
inline const Interval *operator*() const { return IntStack.top().first; }
|
||||
inline Interval *operator*() { return IntStack.top().first; }
|
||||
inline const Interval *operator*() const { return IntStack.back().first; }
|
||||
inline Interval *operator*() { return IntStack.back().first; }
|
||||
inline const Interval *operator->() const { return operator*(); }
|
||||
inline Interval *operator->() { return operator*(); }
|
||||
|
||||
@ -133,8 +133,8 @@ class IntervalIterator {
|
||||
do {
|
||||
// All of the intervals on the stack have been visited. Try visiting
|
||||
// their successors now.
|
||||
Interval::succ_iterator &SuccIt = IntStack.top().second,
|
||||
EndIt = succ_end(IntStack.top().first);
|
||||
Interval::succ_iterator &SuccIt = IntStack.back().second,
|
||||
EndIt = succ_end(IntStack.back().first);
|
||||
while (SuccIt != EndIt) { // Loop over all interval succs
|
||||
bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt));
|
||||
++SuccIt; // Increment iterator
|
||||
@ -142,10 +142,10 @@ class IntervalIterator {
|
||||
}
|
||||
|
||||
// Free interval memory... if necessary
|
||||
if (IOwnMem) delete IntStack.top().first;
|
||||
if (IOwnMem) delete IntStack.back().first;
|
||||
|
||||
// We ran out of successors for this interval... pop off the stack
|
||||
IntStack.pop();
|
||||
IntStack.pop_back();
|
||||
} while (!IntStack.empty());
|
||||
|
||||
return *this;
|
||||
@ -175,7 +175,7 @@ class IntervalIterator {
|
||||
E = GT::child_end(Node); I != E; ++I)
|
||||
ProcessNode(Int, getSourceGraphNode(OrigContainer, *I));
|
||||
|
||||
IntStack.push(std::make_pair(Int, succ_begin(Int)));
|
||||
IntStack.push_back(std::make_pair(Int, succ_begin(Int)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
51
include/llvm/Analysis/Loads.h
Normal file
51
include/llvm/Analysis/Loads.h
Normal file
@ -0,0 +1,51 @@
|
||||
//===- Loads.h - Local load analysis --------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file declares simple local analyses for load instructions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_ANALYSIS_LOADS_H
|
||||
#define LLVM_ANALYSIS_LOADS_H
|
||||
|
||||
#include "llvm/BasicBlock.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AliasAnalysis;
|
||||
class TargetData;
|
||||
|
||||
/// isSafeToLoadUnconditionally - Return true if we know that executing a load
|
||||
/// from this value cannot trap. If it is not obviously safe to load from the
|
||||
/// specified pointer, we do a quick local scan of the basic block containing
|
||||
/// ScanFrom, to determine if the address is already accessed.
|
||||
bool isSafeToLoadUnconditionally(Value *V, Instruction *ScanFrom,
|
||||
unsigned Align, const TargetData *TD = 0);
|
||||
|
||||
/// FindAvailableLoadedValue - Scan the ScanBB block backwards (starting at
|
||||
/// the instruction before ScanFrom) checking to see if we have the value at
|
||||
/// the memory address *Ptr locally available within a small number of
|
||||
/// instructions. If the value is available, return it.
|
||||
///
|
||||
/// If not, return the iterator for the last validated instruction that the
|
||||
/// value would be live through. If we scanned the entire block and didn't
|
||||
/// find something that invalidates *Ptr or provides it, ScanFrom would be
|
||||
/// left at begin() and this returns null. ScanFrom could also be left
|
||||
///
|
||||
/// MaxInstsToScan specifies the maximum instructions to scan in the block.
|
||||
/// If it is set to 0, it will scan the whole block. You can also optionally
|
||||
/// specify an alias analysis implementation, which makes this more precise.
|
||||
Value *FindAvailableLoadedValue(Value *Ptr, BasicBlock *ScanBB,
|
||||
BasicBlock::iterator &ScanFrom,
|
||||
unsigned MaxInstsToScan = 6,
|
||||
AliasAnalysis *AA = 0);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -255,6 +255,27 @@ class LoopBase {
|
||||
/// This method returns null if there is no preheader for the loop.
|
||||
///
|
||||
BlockT *getLoopPreheader() const {
|
||||
// Keep track of nodes outside the loop branching to the header...
|
||||
BlockT *Out = getLoopPredecessor();
|
||||
if (!Out) return 0;
|
||||
|
||||
// Make sure there is only one exit out of the preheader.
|
||||
typedef GraphTraits<BlockT*> BlockTraits;
|
||||
typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);
|
||||
++SI;
|
||||
if (SI != BlockTraits::child_end(Out))
|
||||
return 0; // Multiple exits from the block, must not be a preheader.
|
||||
|
||||
// The predecessor has exactly one successor, so it is a preheader.
|
||||
return Out;
|
||||
}
|
||||
|
||||
/// getLoopPredecessor - If the given loop's header has exactly one unique
|
||||
/// predecessor outside the loop, return it. Otherwise return null.
|
||||
/// This is less strict that the loop "preheader" concept, which requires
|
||||
/// the predecessor to have exactly one successor.
|
||||
///
|
||||
BlockT *getLoopPredecessor() const {
|
||||
// Keep track of nodes outside the loop branching to the header...
|
||||
BlockT *Out = 0;
|
||||
|
||||
@ -264,22 +285,17 @@ class LoopBase {
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(Header),
|
||||
PE = InvBlockTraits::child_end(Header); PI != PE; ++PI)
|
||||
if (!contains(*PI)) { // If the block is not in the loop...
|
||||
if (Out && Out != *PI)
|
||||
PE = InvBlockTraits::child_end(Header); PI != PE; ++PI) {
|
||||
typename InvBlockTraits::NodeType *N = *PI;
|
||||
if (!contains(N)) { // If the block is not in the loop...
|
||||
if (Out && Out != N)
|
||||
return 0; // Multiple predecessors outside the loop
|
||||
Out = *PI;
|
||||
Out = N;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there is only one exit out of the preheader.
|
||||
assert(Out && "Header of loop has no predecessors from outside loop?");
|
||||
typename BlockTraits::ChildIteratorType SI = BlockTraits::child_begin(Out);
|
||||
++SI;
|
||||
if (SI != BlockTraits::child_end(Out))
|
||||
return 0; // Multiple exits from the block, must not be a preheader.
|
||||
|
||||
// If there is exactly one preheader, return it. If there was zero, then
|
||||
// Out is still null.
|
||||
return Out;
|
||||
}
|
||||
|
||||
@ -293,11 +309,13 @@ class LoopBase {
|
||||
typename InvBlockTraits::ChildIteratorType PE =
|
||||
InvBlockTraits::child_end(Header);
|
||||
BlockT *Latch = 0;
|
||||
for (; PI != PE; ++PI)
|
||||
if (contains(*PI)) {
|
||||
for (; PI != PE; ++PI) {
|
||||
typename InvBlockTraits::NodeType *N = *PI;
|
||||
if (contains(N)) {
|
||||
if (Latch) return 0;
|
||||
Latch = *PI;
|
||||
Latch = N;
|
||||
}
|
||||
}
|
||||
|
||||
return Latch;
|
||||
}
|
||||
@ -409,10 +427,11 @@ class LoopBase {
|
||||
for (typename InvBlockTraits::ChildIteratorType PI =
|
||||
InvBlockTraits::child_begin(BB), PE = InvBlockTraits::child_end(BB);
|
||||
PI != PE; ++PI) {
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), *PI))
|
||||
typename InvBlockTraits::NodeType *N = *PI;
|
||||
if (std::binary_search(LoopBBs.begin(), LoopBBs.end(), N))
|
||||
HasInsideLoopPreds = true;
|
||||
else
|
||||
OutsideLoopPreds.push_back(*PI);
|
||||
OutsideLoopPreds.push_back(N);
|
||||
}
|
||||
|
||||
if (BB == getHeader()) {
|
||||
@ -743,9 +762,11 @@ class LoopInfoBase {
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
for (typename InvBlockTraits::ChildIteratorType I =
|
||||
InvBlockTraits::child_begin(BB), E = InvBlockTraits::child_end(BB);
|
||||
I != E; ++I)
|
||||
if (DT.dominates(BB, *I)) // If BB dominates its predecessor...
|
||||
TodoStack.push_back(*I);
|
||||
I != E; ++I) {
|
||||
typename InvBlockTraits::NodeType *N = *I;
|
||||
if (DT.dominates(BB, N)) // If BB dominates its predecessor...
|
||||
TodoStack.push_back(N);
|
||||
}
|
||||
|
||||
if (TodoStack.empty()) return 0; // No backedges to this block...
|
||||
|
||||
|
@ -72,8 +72,8 @@ Value *getMallocArraySize(CallInst *CI, const TargetData *TD,
|
||||
// free Call Utility Functions.
|
||||
//
|
||||
|
||||
/// isFreeCall - Returns true if the value is a call to the builtin free()
|
||||
bool isFreeCall(const Value *I);
|
||||
/// isFreeCall - Returns non-null if the value is a call to the builtin free()
|
||||
const CallInst *isFreeCall(const Value *I);
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
|
@ -343,10 +343,6 @@ namespace llvm {
|
||||
BackedgeTakenInfo HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
|
||||
const Loop *L, bool isSigned);
|
||||
|
||||
/// getLoopPredecessor - If the given loop's header has exactly one unique
|
||||
/// predecessor outside the loop, return it. Otherwise return null.
|
||||
BasicBlock *getLoopPredecessor(const Loop *L);
|
||||
|
||||
/// getPredecessorWithUniqueSuccessorForBB - Return a predecessor of BB
|
||||
/// (which may not be an immediate predecessor) which has exactly one
|
||||
/// successor from which BB is reachable, or null if no such block is
|
||||
@ -530,10 +526,6 @@ namespace llvm {
|
||||
/// widening.
|
||||
const SCEV *getTruncateOrNoop(const SCEV *V, const Type *Ty);
|
||||
|
||||
/// getIntegerSCEV - Given a SCEVable type, create a constant for the
|
||||
/// specified signed integer value and return a SCEV for the constant.
|
||||
const SCEV *getIntegerSCEV(int64_t Val, const Type *Ty);
|
||||
|
||||
/// getUMaxFromMismatchedTypes - Promote the operands to the wider of
|
||||
/// the types using zero-extension, and then perform a umax operation
|
||||
/// with them.
|
||||
|
@ -32,6 +32,7 @@ namespace llvm {
|
||||
std::map<std::pair<const SCEV *, Instruction *>, AssertingVH<Value> >
|
||||
InsertedExpressions;
|
||||
std::set<Value*> InsertedValues;
|
||||
std::set<Value*> InsertedPostIncValues;
|
||||
|
||||
/// PostIncLoops - Addrecs referring to any of the given loops are expanded
|
||||
/// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode
|
||||
@ -102,6 +103,10 @@ namespace llvm {
|
||||
/// clearPostInc - Disable all post-inc expansion.
|
||||
void clearPostInc() {
|
||||
PostIncLoops.clear();
|
||||
|
||||
// When we change the post-inc loop set, cached expansions may no
|
||||
// longer be valid.
|
||||
InsertedPostIncValues.clear();
|
||||
}
|
||||
|
||||
/// disableCanonicalMode - Disable the behavior of expanding expressions in
|
||||
@ -123,6 +128,14 @@ namespace llvm {
|
||||
/// of work to avoid inserting an obviously redundant operation.
|
||||
Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS);
|
||||
|
||||
/// ReuseOrCreateCast - Arange for there to be a cast of V to Ty at IP,
|
||||
/// reusing an existing cast if a suitable one exists, moving an existing
|
||||
/// cast if a suitable one exists but isn't in the right place, or
|
||||
/// or creating a new one.
|
||||
Value *ReuseOrCreateCast(Value *V, const Type *Ty,
|
||||
Instruction::CastOps Op,
|
||||
BasicBlock::iterator IP);
|
||||
|
||||
/// InsertNoopCastOfTo - Insert a cast of V to the specified type,
|
||||
/// which must be possible with a noop cast, doing what we can to
|
||||
/// share the casts.
|
||||
@ -146,7 +159,7 @@ namespace llvm {
|
||||
/// inserted by the code rewriter. If so, the client should not modify the
|
||||
/// instruction.
|
||||
bool isInsertedInstruction(Instruction *I) const {
|
||||
return InsertedValues.count(I);
|
||||
return InsertedValues.count(I) || InsertedPostIncValues.count(I);
|
||||
}
|
||||
|
||||
Value *visitConstant(const SCEVConstant *S) {
|
||||
|
@ -97,7 +97,7 @@ namespace llvm {
|
||||
|
||||
|
||||
|
||||
/// FindScalarValue - Given an aggregrate and an sequence of indices, see if
|
||||
/// FindInsertedValue - Given an aggregrate and an sequence of indices, see if
|
||||
/// the scalar value indexed is already around as a register, for example if
|
||||
/// it were inserted directly into the aggregrate.
|
||||
///
|
||||
|
@ -40,7 +40,8 @@ namespace llvm {
|
||||
std::string *ErrMsg = 0);
|
||||
|
||||
/// WriteBitcodeToFile - Write the specified module to the specified
|
||||
/// raw output stream.
|
||||
/// raw output stream. For streams where it matters, the given stream
|
||||
/// should be in "binary" mode.
|
||||
void WriteBitcodeToFile(const Module *M, raw_ostream &Out);
|
||||
|
||||
/// WriteBitcodeToStream - Write the specified module to the specified
|
||||
|
@ -64,7 +64,7 @@ namespace llvm {
|
||||
/// Target machine description.
|
||||
///
|
||||
TargetMachine &TM;
|
||||
|
||||
|
||||
/// Target Asm Printer information.
|
||||
///
|
||||
const MCAsmInfo *MAI;
|
||||
@ -73,13 +73,13 @@ namespace llvm {
|
||||
/// streaming. This owns all of the global MC-related objects for the
|
||||
/// generated translation unit.
|
||||
MCContext &OutContext;
|
||||
|
||||
|
||||
/// OutStreamer - This is the MCStreamer object for the file we are
|
||||
/// generating. This contains the transient state for the current
|
||||
/// translation unit that we are generating (such as the current section
|
||||
/// etc).
|
||||
MCStreamer &OutStreamer;
|
||||
|
||||
|
||||
/// The current machine function.
|
||||
const MachineFunction *MF;
|
||||
|
||||
@ -94,30 +94,30 @@ namespace llvm {
|
||||
/// beginning of each call to runOnMachineFunction().
|
||||
///
|
||||
MCSymbol *CurrentFnSym;
|
||||
|
||||
|
||||
private:
|
||||
// GCMetadataPrinters - The garbage collection metadata printer table.
|
||||
void *GCMetadataPrinters; // Really a DenseMap.
|
||||
|
||||
|
||||
/// VerboseAsm - Emit comments in assembly output if this is true.
|
||||
///
|
||||
bool VerboseAsm;
|
||||
static char ID;
|
||||
|
||||
|
||||
/// If VerboseAsm is set, a pointer to the loop info for this
|
||||
/// function.
|
||||
MachineLoopInfo *LI;
|
||||
|
||||
/// DD - If the target supports dwarf debug info, this pointer is non-null.
|
||||
DwarfDebug *DD;
|
||||
|
||||
|
||||
/// DE - If the target supports dwarf exception info, this pointer is
|
||||
/// non-null.
|
||||
DwarfException *DE;
|
||||
|
||||
|
||||
protected:
|
||||
explicit AsmPrinter(TargetMachine &TM, MCStreamer &Streamer);
|
||||
|
||||
|
||||
public:
|
||||
virtual ~AsmPrinter();
|
||||
|
||||
@ -128,7 +128,7 @@ namespace llvm {
|
||||
/// getFunctionNumber - Return a unique ID for the current function.
|
||||
///
|
||||
unsigned getFunctionNumber() const;
|
||||
|
||||
|
||||
/// getObjFileLowering - Return information about object file lowering.
|
||||
const TargetLoweringObjectFile &getObjFileLowering() const;
|
||||
|
||||
@ -137,16 +137,16 @@ namespace llvm {
|
||||
|
||||
/// getCurrentSection() - Return the current section we are emitting to.
|
||||
const MCSection *getCurrentSection() const;
|
||||
|
||||
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// MachineFunctionPass Implementation.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
|
||||
/// getAnalysisUsage - Record analysis usage.
|
||||
///
|
||||
///
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
|
||||
/// doInitialization - Set up the AsmPrinter when we are working on a new
|
||||
/// module. If your pass overrides this, it must make sure to explicitly
|
||||
/// call this implementation.
|
||||
@ -155,7 +155,7 @@ namespace llvm {
|
||||
/// doFinalization - Shut down the asmprinter. If you override this in your
|
||||
/// pass, you must make sure to call it explicitly.
|
||||
bool doFinalization(Module &M);
|
||||
|
||||
|
||||
/// runOnMachineFunction - Emit the specified function out to the
|
||||
/// OutStreamer.
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF) {
|
||||
@ -163,20 +163,20 @@ namespace llvm {
|
||||
EmitFunctionHeader();
|
||||
EmitFunctionBody();
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Coarse grained IR lowering routines.
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
|
||||
/// SetupMachineFunction - This should be called when a new MachineFunction
|
||||
/// is being processed from runOnMachineFunction.
|
||||
void SetupMachineFunction(MachineFunction &MF);
|
||||
|
||||
|
||||
/// EmitFunctionHeader - This method emits the header for the current
|
||||
/// function.
|
||||
void EmitFunctionHeader();
|
||||
|
||||
|
||||
/// EmitFunctionBody - This method emits the body and trailer for a
|
||||
/// function.
|
||||
void EmitFunctionBody();
|
||||
@ -187,15 +187,15 @@ namespace llvm {
|
||||
/// the code generator.
|
||||
///
|
||||
virtual void EmitConstantPool();
|
||||
|
||||
/// EmitJumpTableInfo - Print assembly representations of the jump tables
|
||||
/// used by the current function to the current output stream.
|
||||
|
||||
/// EmitJumpTableInfo - Print assembly representations of the jump tables
|
||||
/// used by the current function to the current output stream.
|
||||
///
|
||||
void EmitJumpTableInfo();
|
||||
|
||||
|
||||
/// EmitGlobalVariable - Emit the specified global variable to the .s file.
|
||||
virtual void EmitGlobalVariable(const GlobalVariable *GV);
|
||||
|
||||
|
||||
/// EmitSpecialLLVMGlobal - Check to see if the specified global is a
|
||||
/// special global used by LLVM. If so, emit it and return true, otherwise
|
||||
/// do nothing and return false.
|
||||
@ -208,54 +208,54 @@ namespace llvm {
|
||||
/// if required for correctness.
|
||||
///
|
||||
void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0) const;
|
||||
|
||||
|
||||
/// EmitBasicBlockStart - This method prints the label for the specified
|
||||
/// MachineBasicBlock, an alignment (if present) and a comment describing
|
||||
/// it if appropriate.
|
||||
void EmitBasicBlockStart(const MachineBasicBlock *MBB) const;
|
||||
|
||||
|
||||
/// EmitGlobalConstant - Print a general LLVM constant to the .s file.
|
||||
void EmitGlobalConstant(const Constant *CV, unsigned AddrSpace = 0);
|
||||
|
||||
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Overridable Hooks
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
|
||||
// Targets can, or in the case of EmitInstruction, must implement these to
|
||||
// customize output.
|
||||
|
||||
|
||||
/// EmitStartOfAsmFile - This virtual method can be overridden by targets
|
||||
/// that want to emit something at the start of their file.
|
||||
virtual void EmitStartOfAsmFile(Module &) {}
|
||||
|
||||
|
||||
/// EmitEndOfAsmFile - This virtual method can be overridden by targets that
|
||||
/// want to emit something at the end of their file.
|
||||
virtual void EmitEndOfAsmFile(Module &) {}
|
||||
|
||||
|
||||
/// EmitFunctionBodyStart - Targets can override this to emit stuff before
|
||||
/// the first basic block in the function.
|
||||
virtual void EmitFunctionBodyStart() {}
|
||||
|
||||
|
||||
/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
|
||||
/// the last basic block in the function.
|
||||
virtual void EmitFunctionBodyEnd() {}
|
||||
|
||||
|
||||
/// EmitInstruction - Targets should implement this to emit instructions.
|
||||
virtual void EmitInstruction(const MachineInstr *) {
|
||||
assert(0 && "EmitInstruction not implemented");
|
||||
}
|
||||
|
||||
|
||||
virtual void EmitFunctionEntryLabel();
|
||||
|
||||
|
||||
virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV);
|
||||
|
||||
|
||||
/// isBlockOnlyReachableByFallthough - Return true if the basic block has
|
||||
/// exactly one predecessor and the control transfer mechanism between
|
||||
/// the predecessor and this block is a fall-through.
|
||||
virtual bool
|
||||
isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const;
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Symbol Lowering Routines.
|
||||
//===------------------------------------------------------------------===//
|
||||
@ -264,23 +264,23 @@ namespace llvm {
|
||||
/// GetTempSymbol - Return the MCSymbol corresponding to the assembler
|
||||
/// temporary label with the specified stem and unique ID.
|
||||
MCSymbol *GetTempSymbol(StringRef Name, unsigned ID) const;
|
||||
|
||||
|
||||
/// GetTempSymbol - Return an assembler temporary label with the specified
|
||||
/// stem.
|
||||
MCSymbol *GetTempSymbol(StringRef Name) const;
|
||||
|
||||
|
||||
|
||||
|
||||
/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
|
||||
/// global value name as its base, with the specified suffix, and where the
|
||||
/// symbol is forced to have private linkage if ForcePrivate is true.
|
||||
MCSymbol *GetSymbolWithGlobalValueBase(const GlobalValue *GV,
|
||||
StringRef Suffix,
|
||||
bool ForcePrivate = true) const;
|
||||
|
||||
|
||||
/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
|
||||
/// ExternalSymbol.
|
||||
MCSymbol *GetExternalSymbolSymbol(StringRef Sym) const;
|
||||
|
||||
|
||||
/// GetCPISymbol - Return the symbol for the specified constant pool entry.
|
||||
MCSymbol *GetCPISymbol(unsigned CPID) const;
|
||||
|
||||
@ -302,42 +302,42 @@ namespace llvm {
|
||||
public:
|
||||
/// printOffset - This is just convenient handler for printing offsets.
|
||||
void printOffset(int64_t Offset, raw_ostream &OS) const;
|
||||
|
||||
|
||||
/// EmitInt8 - Emit a byte directive and value.
|
||||
///
|
||||
void EmitInt8(int Value) const;
|
||||
|
||||
|
||||
/// EmitInt16 - Emit a short directive and value.
|
||||
///
|
||||
void EmitInt16(int Value) const;
|
||||
|
||||
|
||||
/// EmitInt32 - Emit a long directive and value.
|
||||
///
|
||||
void EmitInt32(int Value) const;
|
||||
|
||||
|
||||
/// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size
|
||||
/// in bytes of the directive is specified by Size and Hi/Lo specify the
|
||||
/// labels. This implicitly uses .set if it is available.
|
||||
void EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
|
||||
unsigned Size) const;
|
||||
|
||||
/// EmitLabelOffsetDifference - Emit something like ".long Hi+Offset-Lo"
|
||||
|
||||
/// EmitLabelOffsetDifference - Emit something like ".long Hi+Offset-Lo"
|
||||
/// where the size in bytes of the directive is specified by Size and Hi/Lo
|
||||
/// specify the labels. This implicitly uses .set if it is available.
|
||||
void EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset,
|
||||
const MCSymbol *Lo, unsigned Size) const;
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Dwarf Emission Helper Routines
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
|
||||
/// EmitSLEB128 - emit the specified signed leb128 value.
|
||||
void EmitSLEB128(int Value, const char *Desc = 0) const;
|
||||
|
||||
|
||||
/// EmitULEB128 - emit the specified unsigned leb128 value.
|
||||
void EmitULEB128(unsigned Value, const char *Desc = 0,
|
||||
unsigned PadTo = 0) const;
|
||||
|
||||
|
||||
/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
|
||||
void EmitCFAByte(unsigned Val) const;
|
||||
|
||||
@ -346,15 +346,15 @@ namespace llvm {
|
||||
/// describing the encoding. Desc is a string saying what the encoding is
|
||||
/// specifying (e.g. "LSDA").
|
||||
void EmitEncodingByte(unsigned Val, const char *Desc = 0) const;
|
||||
|
||||
|
||||
/// GetSizeOfEncodedValue - Return the size of the encoding in bytes.
|
||||
unsigned GetSizeOfEncodedValue(unsigned Encoding) const;
|
||||
|
||||
|
||||
/// EmitReference - Emit a reference to a label with a specified encoding.
|
||||
///
|
||||
void EmitReference(const MCSymbol *Sym, unsigned Encoding) const;
|
||||
void EmitReference(const GlobalValue *GV, unsigned Encoding) const;
|
||||
|
||||
|
||||
/// EmitSectionOffset - Emit the 4-byte offset of Label from the start of
|
||||
/// its section. This can be done with a special directive if the target
|
||||
/// supports it (e.g. cygwin) or by emitting it as an offset from a label at
|
||||
@ -372,20 +372,20 @@ namespace llvm {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Dwarf Lowering Routines
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
|
||||
/// EmitFrameMoves - Emit frame instructions to describe the layout of the
|
||||
/// frame.
|
||||
void EmitFrameMoves(const std::vector<MachineMove> &Moves,
|
||||
void EmitFrameMoves(const std::vector<MachineMove> &Moves,
|
||||
MCSymbol *BaseLabel, bool isEH) const;
|
||||
|
||||
|
||||
|
||||
|
||||
//===------------------------------------------------------------------===//
|
||||
// Inline Asm Support
|
||||
//===------------------------------------------------------------------===//
|
||||
public:
|
||||
// These are hooks that targets can override to implement inline asm
|
||||
// support. These should probably be moved out of AsmPrinter someday.
|
||||
|
||||
|
||||
/// PrintSpecial - Print information related to the specified machine instr
|
||||
/// that is independent of the operand, and may be independent of the instr
|
||||
/// itself. This can be useful for portably encoding the comment character
|
||||
@ -394,7 +394,7 @@ namespace llvm {
|
||||
/// for their own strange codes.
|
||||
virtual void PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
|
||||
const char *Code) const;
|
||||
|
||||
|
||||
/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
|
||||
/// instruction, using the specified assembler variant. Targets should
|
||||
/// override this to format as appropriate. This method can return true if
|
||||
@ -402,16 +402,16 @@ namespace llvm {
|
||||
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant, const char *ExtraCode,
|
||||
raw_ostream &OS);
|
||||
|
||||
|
||||
/// PrintAsmMemoryOperand - Print the specified operand of MI, an INLINEASM
|
||||
/// instruction, using the specified assembler variant as an address.
|
||||
/// Targets should override this to format as appropriate. This method can
|
||||
/// return true if the operand is erroneous.
|
||||
virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
unsigned AsmVariant,
|
||||
unsigned AsmVariant,
|
||||
const char *ExtraCode,
|
||||
raw_ostream &OS);
|
||||
|
||||
|
||||
private:
|
||||
/// Private state for PrintSpecial()
|
||||
// Assign a unique ID to this machine instruction.
|
||||
@ -422,7 +422,7 @@ namespace llvm {
|
||||
|
||||
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
|
||||
void EmitInlineAsm(StringRef Str, unsigned LocCookie) const;
|
||||
|
||||
|
||||
/// EmitInlineAsm - This method formats and emits the specified machine
|
||||
/// instruction that is an inline asm.
|
||||
void EmitInlineAsm(const MachineInstr *MI) const;
|
||||
@ -430,13 +430,13 @@ namespace llvm {
|
||||
//===------------------------------------------------------------------===//
|
||||
// Internal Implementation Details
|
||||
//===------------------------------------------------------------------===//
|
||||
|
||||
|
||||
/// EmitVisibility - This emits visibility information about symbol, if
|
||||
/// this is suported by the target.
|
||||
void EmitVisibility(MCSymbol *Sym, unsigned Visibility) const;
|
||||
|
||||
|
||||
void EmitLinkage(unsigned Linkage, MCSymbol *GVSym) const;
|
||||
|
||||
|
||||
void EmitJumpTableEntry(const MachineJumpTableInfo *MJTI,
|
||||
const MachineBasicBlock *MBB,
|
||||
unsigned uid) const;
|
||||
|
@ -17,14 +17,13 @@
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/CodeGen/SelectionDAGNodes.h"
|
||||
#include "llvm/Target/TargetCallingConv.h"
|
||||
#include "llvm/CallingConv.h"
|
||||
|
||||
namespace llvm {
|
||||
class TargetRegisterInfo;
|
||||
class TargetMachine;
|
||||
class CCState;
|
||||
class SDNode;
|
||||
|
||||
/// CCValAssign - Represent assignment of one arg/retval to a location.
|
||||
class CCValAssign {
|
||||
@ -35,6 +34,9 @@ class CCValAssign {
|
||||
ZExt, // The value is zero extended in the location.
|
||||
AExt, // The value is extended with undefined upper bits.
|
||||
BCvt, // The value is bit-converted in the location.
|
||||
VExt, // The value is vector-widened in the location.
|
||||
// FIXME: Not implemented yet. Code that uses AExt to mean
|
||||
// vector-widen should be fixed to use VExt instead.
|
||||
Indirect // The location contains pointer to the value.
|
||||
// TODO: a subset of the value is in the location.
|
||||
};
|
||||
@ -186,8 +188,7 @@ class CCState {
|
||||
/// CheckReturn - Analyze the return values of a function, returning
|
||||
/// true if the return can be performed without sret-demotion, and
|
||||
/// false otherwise.
|
||||
bool CheckReturn(const SmallVectorImpl<EVT> &OutTys,
|
||||
const SmallVectorImpl<ISD::ArgFlagsTy> &ArgsFlags,
|
||||
bool CheckReturn(const SmallVectorImpl<ISD::OutputArg> &ArgsFlags,
|
||||
CCAssignFn Fn);
|
||||
|
||||
/// AnalyzeCallOperands - Analyze the outgoing arguments to a call,
|
||||
|
@ -19,11 +19,13 @@
|
||||
#include "llvm/ADT/SmallSet.h"
|
||||
#endif
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AllocaInst;
|
||||
class ConstantFP;
|
||||
class FunctionLoweringInfo;
|
||||
class Instruction;
|
||||
class MachineBasicBlock;
|
||||
class MachineConstantPool;
|
||||
@ -36,22 +38,15 @@ class TargetInstrInfo;
|
||||
class TargetLowering;
|
||||
class TargetMachine;
|
||||
class TargetRegisterClass;
|
||||
class TargetRegisterInfo;
|
||||
|
||||
/// FastISel - This is a fast-path instruction selection class that
|
||||
/// generates poor code and doesn't support illegal types or non-trivial
|
||||
/// lowering, but runs quickly.
|
||||
class FastISel {
|
||||
protected:
|
||||
MachineBasicBlock *MBB;
|
||||
DenseMap<const Value *, unsigned> LocalValueMap;
|
||||
DenseMap<const Value *, unsigned> &ValueMap;
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &MBBMap;
|
||||
DenseMap<const AllocaInst *, int> &StaticAllocaMap;
|
||||
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate;
|
||||
#ifndef NDEBUG
|
||||
SmallSet<const Instruction *, 8> &CatchInfoLost;
|
||||
#endif
|
||||
MachineFunction &MF;
|
||||
FunctionLoweringInfo &FuncInfo;
|
||||
MachineRegisterInfo &MRI;
|
||||
MachineFrameInfo &MFI;
|
||||
MachineConstantPool &MCP;
|
||||
@ -60,23 +55,22 @@ class FastISel {
|
||||
const TargetData &TD;
|
||||
const TargetInstrInfo &TII;
|
||||
const TargetLowering &TLI;
|
||||
bool IsBottomUp;
|
||||
const TargetRegisterInfo &TRI;
|
||||
MachineInstr *LastLocalValue;
|
||||
|
||||
public:
|
||||
/// getLastLocalValue - Return the position of the last instruction
|
||||
/// emitted for materializing constants for use in the current block.
|
||||
MachineInstr *getLastLocalValue() { return LastLocalValue; }
|
||||
|
||||
/// setLastLocalValue - Update the position of the last instruction
|
||||
/// emitted for materializing constants for use in the current block.
|
||||
void setLastLocalValue(MachineInstr *I) { LastLocalValue = I; }
|
||||
|
||||
/// startNewBlock - Set the current block to which generated machine
|
||||
/// instructions will be appended, and clear the local CSE map.
|
||||
///
|
||||
void startNewBlock(MachineBasicBlock *mbb) {
|
||||
setCurrentBlock(mbb);
|
||||
LocalValueMap.clear();
|
||||
}
|
||||
|
||||
/// setCurrentBlock - Set the current block to which generated machine
|
||||
/// instructions will be appended.
|
||||
///
|
||||
void setCurrentBlock(MachineBasicBlock *mbb) {
|
||||
MBB = mbb;
|
||||
}
|
||||
void startNewBlock();
|
||||
|
||||
/// getCurDebugLoc() - Return current debug location information.
|
||||
DebugLoc getCurDebugLoc() const { return DL; }
|
||||
@ -108,18 +102,21 @@ class FastISel {
|
||||
/// index value.
|
||||
std::pair<unsigned, bool> getRegForGEPIndex(const Value *V);
|
||||
|
||||
/// recomputeInsertPt - Reset InsertPt to prepare for insterting instructions
|
||||
/// into the current block.
|
||||
void recomputeInsertPt();
|
||||
|
||||
/// enterLocalValueArea - Prepare InsertPt to begin inserting instructions
|
||||
/// into the local value area and return the old insert position.
|
||||
MachineBasicBlock::iterator enterLocalValueArea();
|
||||
|
||||
/// leaveLocalValueArea - Reset InsertPt to the given old insert position
|
||||
void leaveLocalValueArea(MachineBasicBlock::iterator OldInsertPt);
|
||||
|
||||
virtual ~FastISel();
|
||||
|
||||
protected:
|
||||
FastISel(MachineFunction &mf,
|
||||
DenseMap<const Value *, unsigned> &vm,
|
||||
DenseMap<const BasicBlock *, MachineBasicBlock *> &bm,
|
||||
DenseMap<const AllocaInst *, int> &am,
|
||||
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate
|
||||
#ifndef NDEBUG
|
||||
, SmallSet<const Instruction *, 8> &cil
|
||||
#endif
|
||||
);
|
||||
explicit FastISel(FunctionLoweringInfo &funcInfo);
|
||||
|
||||
/// TargetSelectInstruction - This method is called by target-independent
|
||||
/// code when the normal FastISel process fails to select an instruction.
|
||||
@ -286,7 +283,7 @@ class FastISel {
|
||||
/// FastEmitBranch - Emit an unconditional branch to the given block,
|
||||
/// unless it is the immediate (fall-through) successor, and update
|
||||
/// the CFG.
|
||||
void FastEmitBranch(MachineBasicBlock *MBB);
|
||||
void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL);
|
||||
|
||||
unsigned UpdateValueMap(const Value* I, unsigned Reg);
|
||||
|
||||
@ -305,6 +302,8 @@ class FastISel {
|
||||
}
|
||||
|
||||
private:
|
||||
bool SelectLoad(const User *I);
|
||||
|
||||
bool SelectBinaryOp(const User *I, unsigned ISDOpcode);
|
||||
|
||||
bool SelectFNeg(const User *I);
|
||||
|
@ -12,8 +12,8 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef FUNCTIONLOWERINGINFO_H
|
||||
#define FUNCTIONLOWERINGINFO_H
|
||||
#ifndef LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H
|
||||
#define LLVM_CODEGEN_FUNCTIONLOWERINGINFO_H
|
||||
|
||||
#include "llvm/InlineAsm.h"
|
||||
#include "llvm/Instructions.h"
|
||||
@ -25,6 +25,7 @@
|
||||
#endif
|
||||
#include "llvm/CodeGen/ValueTypes.h"
|
||||
#include "llvm/CodeGen/ISDOpcodes.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
#include "llvm/Support/CallSite.h"
|
||||
#include <vector>
|
||||
|
||||
@ -80,6 +81,15 @@ class FunctionLoweringInfo {
|
||||
/// function arguments that are inserted after scheduling is completed.
|
||||
SmallVector<MachineInstr*, 8> ArgDbgValues;
|
||||
|
||||
/// RegFixups - Registers which need to be replaced after isel is done.
|
||||
DenseMap<unsigned, unsigned> RegFixups;
|
||||
|
||||
/// MBB - The current block.
|
||||
MachineBasicBlock *MBB;
|
||||
|
||||
/// MBB - The current insert position inside the current block.
|
||||
MachineBasicBlock::iterator InsertPt;
|
||||
|
||||
#ifndef NDEBUG
|
||||
SmallSet<const Instruction *, 8> CatchInfoLost;
|
||||
SmallSet<const Instruction *, 8> CatchInfoFound;
|
||||
@ -106,27 +116,27 @@ class FunctionLoweringInfo {
|
||||
/// set - Initialize this FunctionLoweringInfo with the given Function
|
||||
/// and its associated MachineFunction.
|
||||
///
|
||||
void set(const Function &Fn, MachineFunction &MF, bool EnableFastISel);
|
||||
void set(const Function &Fn, MachineFunction &MF);
|
||||
|
||||
/// clear - Clear out all the function-specific state. This returns this
|
||||
/// FunctionLoweringInfo to an empty state, ready to be used for a
|
||||
/// different function.
|
||||
void clear();
|
||||
|
||||
unsigned MakeReg(EVT VT);
|
||||
|
||||
/// isExportedInst - Return true if the specified value is an instruction
|
||||
/// exported from its block.
|
||||
bool isExportedInst(const Value *V) {
|
||||
return ValueMap.count(V);
|
||||
}
|
||||
|
||||
unsigned CreateRegForValue(const Value *V);
|
||||
unsigned CreateReg(EVT VT);
|
||||
|
||||
unsigned CreateRegs(const Type *Ty);
|
||||
|
||||
unsigned InitializeRegForValue(const Value *V) {
|
||||
unsigned &R = ValueMap[V];
|
||||
assert(R == 0 && "Already initialized this value register!");
|
||||
return R = CreateRegForValue(V);
|
||||
return R = CreateRegs(V->getType());
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
//===-- GCMetadata.h - Garbage collector metadata -------------------------===//
|
||||
//===-- GCMetadata.h - Garbage collector metadata ---------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
@ -14,7 +14,7 @@
|
||||
//
|
||||
// The GCFunctionInfo class logs the data necessary to build a type accurate
|
||||
// stack map. The code generator outputs:
|
||||
//
|
||||
//
|
||||
// - Safe points as specified by the GCStrategy's NeededSafePoints.
|
||||
// - Stack offsets for GC roots, as specified by calls to llvm.gcroot
|
||||
//
|
||||
@ -42,10 +42,10 @@ namespace llvm {
|
||||
class GCStrategy;
|
||||
class Constant;
|
||||
class MCSymbol;
|
||||
|
||||
|
||||
namespace GC {
|
||||
/// PointKind - The type of a collector-safe point.
|
||||
///
|
||||
///
|
||||
enum PointKind {
|
||||
Loop, //< Instr is a loop (backwards branch).
|
||||
Return, //< Instr is a return instruction.
|
||||
@ -53,138 +53,138 @@ namespace llvm {
|
||||
PostCall //< Instr is the return address of a call.
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// GCPoint - Metadata for a collector-safe point in machine code.
|
||||
///
|
||||
///
|
||||
struct GCPoint {
|
||||
GC::PointKind Kind; //< The kind of the safe point.
|
||||
MCSymbol *Label; //< A label.
|
||||
|
||||
|
||||
GCPoint(GC::PointKind K, MCSymbol *L) : Kind(K), Label(L) {}
|
||||
};
|
||||
|
||||
|
||||
/// GCRoot - Metadata for a pointer to an object managed by the garbage
|
||||
/// collector.
|
||||
struct GCRoot {
|
||||
int Num; //< Usually a frame index.
|
||||
int StackOffset; //< Offset from the stack pointer.
|
||||
const Constant *Metadata;//< Metadata straight from the call to llvm.gcroot.
|
||||
|
||||
|
||||
GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// GCFunctionInfo - Garbage collection metadata for a single function.
|
||||
///
|
||||
///
|
||||
class GCFunctionInfo {
|
||||
public:
|
||||
typedef std::vector<GCPoint>::iterator iterator;
|
||||
typedef std::vector<GCRoot>::iterator roots_iterator;
|
||||
typedef std::vector<GCRoot>::const_iterator live_iterator;
|
||||
|
||||
|
||||
private:
|
||||
const Function &F;
|
||||
GCStrategy &S;
|
||||
uint64_t FrameSize;
|
||||
std::vector<GCRoot> Roots;
|
||||
std::vector<GCPoint> SafePoints;
|
||||
|
||||
|
||||
// FIXME: Liveness. A 2D BitVector, perhaps?
|
||||
//
|
||||
//
|
||||
// BitVector Liveness;
|
||||
//
|
||||
//
|
||||
// bool islive(int point, int root) =
|
||||
// Liveness[point * SafePoints.size() + root]
|
||||
//
|
||||
//
|
||||
// The bit vector is the more compact representation where >3.2% of roots
|
||||
// are live per safe point (1.5% on 64-bit hosts).
|
||||
|
||||
|
||||
public:
|
||||
GCFunctionInfo(const Function &F, GCStrategy &S);
|
||||
~GCFunctionInfo();
|
||||
|
||||
|
||||
/// getFunction - Return the function to which this metadata applies.
|
||||
///
|
||||
///
|
||||
const Function &getFunction() const { return F; }
|
||||
|
||||
|
||||
/// getStrategy - Return the GC strategy for the function.
|
||||
///
|
||||
///
|
||||
GCStrategy &getStrategy() { return S; }
|
||||
|
||||
|
||||
/// addStackRoot - Registers a root that lives on the stack. Num is the
|
||||
/// stack object ID for the alloca (if the code generator is
|
||||
// using MachineFrameInfo).
|
||||
void addStackRoot(int Num, const Constant *Metadata) {
|
||||
Roots.push_back(GCRoot(Num, Metadata));
|
||||
}
|
||||
|
||||
|
||||
/// addSafePoint - Notes the existence of a safe point. Num is the ID of the
|
||||
/// label just prior to the safe point (if the code generator is using
|
||||
/// label just prior to the safe point (if the code generator is using
|
||||
/// MachineModuleInfo).
|
||||
void addSafePoint(GC::PointKind Kind, MCSymbol *Label) {
|
||||
SafePoints.push_back(GCPoint(Kind, Label));
|
||||
}
|
||||
|
||||
|
||||
/// getFrameSize/setFrameSize - Records the function's frame size.
|
||||
///
|
||||
///
|
||||
uint64_t getFrameSize() const { return FrameSize; }
|
||||
void setFrameSize(uint64_t S) { FrameSize = S; }
|
||||
|
||||
|
||||
/// begin/end - Iterators for safe points.
|
||||
///
|
||||
///
|
||||
iterator begin() { return SafePoints.begin(); }
|
||||
iterator end() { return SafePoints.end(); }
|
||||
size_t size() const { return SafePoints.size(); }
|
||||
|
||||
|
||||
/// roots_begin/roots_end - Iterators for all roots in the function.
|
||||
///
|
||||
///
|
||||
roots_iterator roots_begin() { return Roots.begin(); }
|
||||
roots_iterator roots_end () { return Roots.end(); }
|
||||
size_t roots_size() const { return Roots.size(); }
|
||||
|
||||
|
||||
/// live_begin/live_end - Iterators for live roots at a given safe point.
|
||||
///
|
||||
///
|
||||
live_iterator live_begin(const iterator &p) { return roots_begin(); }
|
||||
live_iterator live_end (const iterator &p) { return roots_end(); }
|
||||
size_t live_size(const iterator &p) const { return roots_size(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/// GCModuleInfo - Garbage collection metadata for a whole module.
|
||||
///
|
||||
///
|
||||
class GCModuleInfo : public ImmutablePass {
|
||||
typedef StringMap<GCStrategy*> strategy_map_type;
|
||||
typedef std::vector<GCStrategy*> list_type;
|
||||
typedef DenseMap<const Function*,GCFunctionInfo*> finfo_map_type;
|
||||
|
||||
|
||||
strategy_map_type StrategyMap;
|
||||
list_type StrategyList;
|
||||
finfo_map_type FInfoMap;
|
||||
|
||||
|
||||
GCStrategy *getOrCreateStrategy(const Module *M, const std::string &Name);
|
||||
|
||||
|
||||
public:
|
||||
typedef list_type::const_iterator iterator;
|
||||
|
||||
|
||||
static char ID;
|
||||
|
||||
|
||||
GCModuleInfo();
|
||||
~GCModuleInfo();
|
||||
|
||||
|
||||
/// clear - Resets the pass. The metadata deleter pass calls this.
|
||||
///
|
||||
///
|
||||
void clear();
|
||||
|
||||
|
||||
/// begin/end - Iterators for used strategies.
|
||||
///
|
||||
///
|
||||
iterator begin() const { return StrategyList.begin(); }
|
||||
iterator end() const { return StrategyList.end(); }
|
||||
|
||||
|
||||
/// get - Look up function metadata.
|
||||
///
|
||||
///
|
||||
GCFunctionInfo &getFunctionInfo(const Function &F);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -25,49 +25,49 @@
|
||||
#include "llvm/Support/Registry.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
|
||||
class GCMetadataPrinter;
|
||||
|
||||
|
||||
/// GCMetadataPrinterRegistry - The GC assembly printer registry uses all the
|
||||
/// defaults from Registry.
|
||||
typedef Registry<GCMetadataPrinter> GCMetadataPrinterRegistry;
|
||||
|
||||
|
||||
/// GCMetadataPrinter - Emits GC metadata as assembly code.
|
||||
///
|
||||
///
|
||||
class GCMetadataPrinter {
|
||||
public:
|
||||
typedef GCStrategy::list_type list_type;
|
||||
typedef GCStrategy::iterator iterator;
|
||||
|
||||
|
||||
private:
|
||||
GCStrategy *S;
|
||||
|
||||
|
||||
friend class AsmPrinter;
|
||||
|
||||
|
||||
protected:
|
||||
// May only be subclassed.
|
||||
GCMetadataPrinter();
|
||||
|
||||
|
||||
// Do not implement.
|
||||
GCMetadataPrinter(const GCMetadataPrinter &);
|
||||
GCMetadataPrinter &operator=(const GCMetadataPrinter &);
|
||||
|
||||
|
||||
public:
|
||||
GCStrategy &getStrategy() { return *S; }
|
||||
const Module &getModule() const { return S->getModule(); }
|
||||
|
||||
|
||||
/// begin/end - Iterate over the collected function metadata.
|
||||
iterator begin() { return S->begin(); }
|
||||
iterator end() { return S->end(); }
|
||||
|
||||
|
||||
/// beginAssembly/finishAssembly - Emit module metadata as assembly code.
|
||||
virtual void beginAssembly(AsmPrinter &AP);
|
||||
|
||||
|
||||
virtual void finishAssembly(AsmPrinter &AP);
|
||||
|
||||
|
||||
virtual ~GCMetadataPrinter();
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -130,7 +130,7 @@ namespace ISD {
|
||||
/// This node represents a target intrinsic function with no side effects.
|
||||
/// The first operand is the ID number of the intrinsic from the
|
||||
/// llvm::Intrinsic namespace. The operands to the intrinsic follow. The
|
||||
/// node has returns the result of the intrinsic.
|
||||
/// node returns the result of the intrinsic.
|
||||
INTRINSIC_WO_CHAIN,
|
||||
|
||||
/// RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...)
|
||||
@ -508,8 +508,9 @@ namespace ISD {
|
||||
CALLSEQ_START, // Beginning of a call sequence
|
||||
CALLSEQ_END, // End of a call sequence
|
||||
|
||||
// VAARG - VAARG has three operands: an input chain, a pointer, and a
|
||||
// SRCVALUE. It returns a pair of values: the vaarg value and a new chain.
|
||||
// VAARG - VAARG has four operands: an input chain, a pointer, a SRCVALUE,
|
||||
// and the alignment. It returns a pair of values: the vaarg value and a
|
||||
// new chain.
|
||||
VAARG,
|
||||
|
||||
// VACOPY - VACOPY has five operands: an input chain, a destination pointer,
|
||||
|
@ -33,7 +33,6 @@ namespace {
|
||||
|
||||
(void) llvm::createDeadMachineInstructionElimPass();
|
||||
|
||||
(void) llvm::createLocalRegisterAllocator();
|
||||
(void) llvm::createFastRegisterAllocator();
|
||||
(void) llvm::createLinearScanRegisterAllocator();
|
||||
(void) llvm::createPBQPRegisterAllocator();
|
||||
|
@ -53,7 +53,7 @@ namespace llvm {
|
||||
class VNInfo {
|
||||
private:
|
||||
enum {
|
||||
HAS_PHI_KILL = 1,
|
||||
HAS_PHI_KILL = 1,
|
||||
REDEF_BY_EC = 1 << 1,
|
||||
IS_PHI_DEF = 1 << 2,
|
||||
IS_UNUSED = 1 << 3,
|
||||
@ -67,22 +67,14 @@ namespace llvm {
|
||||
} cr;
|
||||
|
||||
public:
|
||||
typedef SpecificBumpPtrAllocator<VNInfo> Allocator;
|
||||
typedef SmallVector<SlotIndex, 4> KillSet;
|
||||
typedef BumpPtrAllocator Allocator;
|
||||
|
||||
/// The ID number of this value.
|
||||
unsigned id;
|
||||
|
||||
|
||||
/// The index of the defining instruction (if isDefAccurate() returns true).
|
||||
SlotIndex def;
|
||||
|
||||
KillSet kills;
|
||||
|
||||
/*
|
||||
VNInfo(LiveIntervals &li_)
|
||||
: defflags(IS_UNUSED), id(~1U) { cr.copy = 0; }
|
||||
*/
|
||||
|
||||
/// VNInfo constructor.
|
||||
/// d is presumed to point to the actual defining instr. If it doesn't
|
||||
/// setIsDefAccurate(false) should be called after construction.
|
||||
@ -91,7 +83,7 @@ namespace llvm {
|
||||
|
||||
/// VNInfo construtor, copies values from orig, except for the value number.
|
||||
VNInfo(unsigned i, const VNInfo &orig)
|
||||
: flags(orig.flags), cr(orig.cr), id(i), def(orig.def), kills(orig.kills)
|
||||
: flags(orig.flags), cr(orig.cr), id(i), def(orig.def)
|
||||
{ }
|
||||
|
||||
/// Copy from the parameter into this VNInfo.
|
||||
@ -99,7 +91,6 @@ namespace llvm {
|
||||
flags = src.flags;
|
||||
cr = src.cr;
|
||||
def = src.def;
|
||||
kills = src.kills;
|
||||
}
|
||||
|
||||
/// Used for copying value number info.
|
||||
@ -114,7 +105,7 @@ namespace llvm {
|
||||
/// This method should not be called on stack intervals as it may lead to
|
||||
/// undefined behavior.
|
||||
void setCopy(MachineInstr *c) { cr.copy = c; }
|
||||
|
||||
|
||||
/// For a stack interval, returns the reg which this stack interval was
|
||||
/// defined from.
|
||||
/// For a register interval the behaviour of this method is undefined.
|
||||
@ -144,7 +135,7 @@ namespace llvm {
|
||||
else
|
||||
flags &= ~REDEF_BY_EC;
|
||||
}
|
||||
|
||||
|
||||
/// Returns true if this value is defined by a PHI instruction (or was,
|
||||
/// PHI instrucions may have been eliminated).
|
||||
bool isPHIDef() const { return flags & IS_PHI_DEF; }
|
||||
@ -172,49 +163,9 @@ namespace llvm {
|
||||
void setIsDefAccurate(bool defAccurate) {
|
||||
if (defAccurate)
|
||||
flags |= IS_DEF_ACCURATE;
|
||||
else
|
||||
else
|
||||
flags &= ~IS_DEF_ACCURATE;
|
||||
}
|
||||
|
||||
/// Returns true if the given index is a kill of this value.
|
||||
bool isKill(SlotIndex k) const {
|
||||
KillSet::const_iterator
|
||||
i = std::lower_bound(kills.begin(), kills.end(), k);
|
||||
return (i != kills.end() && *i == k);
|
||||
}
|
||||
|
||||
/// addKill - Add a kill instruction index to the specified value
|
||||
/// number.
|
||||
void addKill(SlotIndex k) {
|
||||
if (kills.empty()) {
|
||||
kills.push_back(k);
|
||||
} else {
|
||||
KillSet::iterator
|
||||
i = std::lower_bound(kills.begin(), kills.end(), k);
|
||||
kills.insert(i, k);
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove the specified kill index from this value's kills list.
|
||||
/// Returns true if the value was present, otherwise returns false.
|
||||
bool removeKill(SlotIndex k) {
|
||||
KillSet::iterator i = std::lower_bound(kills.begin(), kills.end(), k);
|
||||
if (i != kills.end() && *i == k) {
|
||||
kills.erase(i);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Remove all kills in the range [s, e).
|
||||
void removeKills(SlotIndex s, SlotIndex e) {
|
||||
KillSet::iterator
|
||||
si = std::lower_bound(kills.begin(), kills.end(), s),
|
||||
se = std::upper_bound(kills.begin(), kills.end(), e);
|
||||
|
||||
kills.erase(si, se);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// LiveRange structure - This represents a simple register range in the
|
||||
@ -258,6 +209,8 @@ namespace llvm {
|
||||
LiveRange(); // DO NOT IMPLEMENT
|
||||
};
|
||||
|
||||
template <> struct isPodLike<LiveRange> { static const bool value = true; };
|
||||
|
||||
raw_ostream& operator<<(raw_ostream& os, const LiveRange &LR);
|
||||
|
||||
|
||||
@ -366,8 +319,8 @@ namespace llvm {
|
||||
/// the instruction that defines the value number.
|
||||
VNInfo *getNextValue(SlotIndex def, MachineInstr *CopyMI,
|
||||
bool isDefAccurate, VNInfo::Allocator &VNInfoAllocator) {
|
||||
VNInfo *VNI = VNInfoAllocator.Allocate();
|
||||
new (VNI) VNInfo((unsigned)valnos.size(), def, CopyMI);
|
||||
VNInfo *VNI =
|
||||
new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), def, CopyMI);
|
||||
VNI->setIsDefAccurate(isDefAccurate);
|
||||
valnos.push_back(VNI);
|
||||
return VNI;
|
||||
@ -377,23 +330,12 @@ namespace llvm {
|
||||
/// for the Value number.
|
||||
VNInfo *createValueCopy(const VNInfo *orig,
|
||||
VNInfo::Allocator &VNInfoAllocator) {
|
||||
VNInfo *VNI = VNInfoAllocator.Allocate();
|
||||
new (VNI) VNInfo((unsigned)valnos.size(), *orig);
|
||||
VNInfo *VNI =
|
||||
new (VNInfoAllocator) VNInfo((unsigned)valnos.size(), *orig);
|
||||
valnos.push_back(VNI);
|
||||
return VNI;
|
||||
}
|
||||
|
||||
/// addKills - Add a number of kills into the VNInfo kill vector. If this
|
||||
/// interval is live at a kill point, then the kill is not added.
|
||||
void addKills(VNInfo *VNI, const VNInfo::KillSet &kills) {
|
||||
for (unsigned i = 0, e = static_cast<unsigned>(kills.size());
|
||||
i != e; ++i) {
|
||||
if (!liveBeforeAndAt(kills[i])) {
|
||||
VNI->addKill(kills[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// isOnlyLROfValNo - Return true if the specified live range is the only
|
||||
/// one defined by the its val#.
|
||||
bool isOnlyLROfValNo(const LiveRange *LR) {
|
||||
@ -472,6 +414,17 @@ namespace llvm {
|
||||
// range.If it does, then check if the previous live range ends at index-1.
|
||||
bool liveBeforeAndAt(SlotIndex index) const;
|
||||
|
||||
/// killedAt - Return true if a live range ends at index. Note that the kill
|
||||
/// point is not contained in the half-open live range. It is usually the
|
||||
/// getDefIndex() slot following its last use.
|
||||
bool killedAt(SlotIndex index) const;
|
||||
|
||||
/// killedInRange - Return true if the interval has kills in [Start,End).
|
||||
/// Note that the kill point is considered the end of a live range, so it is
|
||||
/// not contained in the live range. If a live range ends at End, it won't
|
||||
/// be counted as a kill by this method.
|
||||
bool killedInRange(SlotIndex Start, SlotIndex End) const;
|
||||
|
||||
/// getLiveRangeContaining - Return the live range that contains the
|
||||
/// specified index, or null if there is none.
|
||||
const LiveRange *getLiveRangeContaining(SlotIndex Idx) const {
|
||||
@ -486,6 +439,12 @@ namespace llvm {
|
||||
return I == end() ? 0 : &*I;
|
||||
}
|
||||
|
||||
/// getVNInfoAt - Return the VNInfo that is live at Idx, or NULL.
|
||||
VNInfo *getVNInfoAt(SlotIndex Idx) const {
|
||||
const_iterator I = FindLiveRangeContaining(Idx);
|
||||
return I == end() ? 0 : I->valno;
|
||||
}
|
||||
|
||||
/// FindLiveRangeContaining - Return an iterator to the live range that
|
||||
/// contains the specified index, or end() if there is none.
|
||||
const_iterator FindLiveRangeContaining(SlotIndex Idx) const;
|
||||
|
@ -133,10 +133,9 @@ namespace llvm {
|
||||
bool conflictsWithPhysReg(const LiveInterval &li, VirtRegMap &vrm,
|
||||
unsigned reg);
|
||||
|
||||
/// conflictsWithSubPhysRegRef - Similar to conflictsWithPhysRegRef except
|
||||
/// it checks for sub-register reference and it can check use as well.
|
||||
bool conflictsWithSubPhysRegRef(LiveInterval &li, unsigned Reg,
|
||||
bool CheckUse,
|
||||
/// conflictsWithAliasRef - Similar to conflictsWithPhysRegRef except
|
||||
/// it checks for alias uses and defs.
|
||||
bool conflictsWithAliasRef(LiveInterval &li, unsigned Reg,
|
||||
SmallPtrSet<MachineInstr*,32> &JoinedCopies);
|
||||
|
||||
// Interval creation
|
||||
@ -229,10 +228,6 @@ namespace llvm {
|
||||
|
||||
VNInfo::Allocator& getVNInfoAllocator() { return VNInfoAllocator; }
|
||||
|
||||
/// getVNInfoSourceReg - Helper function that parses the specified VNInfo
|
||||
/// copy field and returns the source register that defines it.
|
||||
unsigned getVNInfoSourceReg(const VNInfo *VNI) const;
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual void releaseMemory();
|
||||
|
||||
@ -249,12 +244,6 @@ namespace llvm {
|
||||
addIntervalsForSpills(const LiveInterval& i,
|
||||
SmallVectorImpl<LiveInterval*> &SpillIs,
|
||||
const MachineLoopInfo *loopInfo, VirtRegMap& vrm);
|
||||
|
||||
/// addIntervalsForSpillsFast - Quickly create new intervals for spilled
|
||||
/// defs / uses without remat or splitting.
|
||||
std::vector<LiveInterval*>
|
||||
addIntervalsForSpillsFast(const LiveInterval &li,
|
||||
const MachineLoopInfo *loopInfo, VirtRegMap &vrm);
|
||||
|
||||
/// spillPhysRegAroundRegDefsUses - Spill the specified physical register
|
||||
/// around all defs and uses of the specified interval. Return true if it
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class Pass;
|
||||
class BasicBlock;
|
||||
class MachineFunction;
|
||||
class MCSymbol;
|
||||
@ -258,6 +259,11 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
|
||||
/// machine basic block (i.e., copies all the successors fromMBB and
|
||||
/// remove all the successors from fromMBB).
|
||||
void transferSuccessors(MachineBasicBlock *fromMBB);
|
||||
|
||||
/// transferSuccessorsAndUpdatePHIs - Transfers all the successors, as
|
||||
/// in transferSuccessors, and update PHI operands in the successor blocks
|
||||
/// which refer to fromMBB to refer to this.
|
||||
void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *fromMBB);
|
||||
|
||||
/// isSuccessor - Return true if the specified MBB is a successor of this
|
||||
/// block.
|
||||
@ -276,11 +282,26 @@ class MachineBasicBlock : public ilist_node<MachineBasicBlock> {
|
||||
/// branch to do so (e.g., a table jump). True is a conservative answer.
|
||||
bool canFallThrough();
|
||||
|
||||
/// Returns a pointer to the first instructon in this block that is not a
|
||||
/// PHINode instruction. When adding instruction to the beginning of the
|
||||
/// basic block, they should be added before the returned value, not before
|
||||
/// the first instruction, which might be PHI.
|
||||
/// Returns end() is there's no non-PHI instruction.
|
||||
iterator getFirstNonPHI();
|
||||
|
||||
/// getFirstTerminator - returns an iterator to the first terminator
|
||||
/// instruction of this basic block. If a terminator does not exist,
|
||||
/// it returns end()
|
||||
iterator getFirstTerminator();
|
||||
|
||||
/// SplitCriticalEdge - Split the critical edge from this block to the
|
||||
/// given successor block, and return the newly created block, or null
|
||||
/// if splitting is not possible.
|
||||
///
|
||||
/// This function updates LiveVariables, MachineDominatorTree, and
|
||||
/// MachineLoopInfo, as applicable.
|
||||
MachineBasicBlock *SplitCriticalEdge(MachineBasicBlock *Succ, Pass *P);
|
||||
|
||||
void pop_front() { Insts.pop_front(); }
|
||||
void pop_back() { Insts.pop_back(); }
|
||||
void push_back(MachineInstr *MI) { Insts.push_back(MI); }
|
||||
|
@ -33,16 +33,14 @@ class BitVector;
|
||||
/// callee saved register in the current frame.
|
||||
class CalleeSavedInfo {
|
||||
unsigned Reg;
|
||||
const TargetRegisterClass *RegClass;
|
||||
int FrameIdx;
|
||||
|
||||
public:
|
||||
CalleeSavedInfo(unsigned R, const TargetRegisterClass *RC, int FI = 0)
|
||||
: Reg(R), RegClass(RC), FrameIdx(FI) {}
|
||||
explicit CalleeSavedInfo(unsigned R, int FI = 0)
|
||||
: Reg(R), FrameIdx(FI) {}
|
||||
|
||||
// Accessors.
|
||||
unsigned getReg() const { return Reg; }
|
||||
const TargetRegisterClass *getRegClass() const { return RegClass; }
|
||||
int getFrameIdx() const { return FrameIdx; }
|
||||
void setFrameIdx(int FI) { FrameIdx = FI; }
|
||||
};
|
||||
@ -100,8 +98,7 @@ class MachineFrameInfo {
|
||||
// cannot alias any other memory objects.
|
||||
bool isSpillSlot;
|
||||
|
||||
StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM,
|
||||
bool isSS)
|
||||
StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, bool isSS)
|
||||
: SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM),
|
||||
isSpillSlot(isSS) {}
|
||||
};
|
||||
@ -352,8 +349,7 @@ class MachineFrameInfo {
|
||||
/// efficiency. By default, fixed objects are immutable. This returns an
|
||||
/// index with a negative value.
|
||||
///
|
||||
int CreateFixedObject(uint64_t Size, int64_t SPOffset,
|
||||
bool Immutable, bool isSS);
|
||||
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable);
|
||||
|
||||
|
||||
/// isFixedObjectIndex - Returns true if the specified index corresponds to a
|
||||
|
@ -34,9 +34,6 @@ class MachineFunctionPass : public FunctionPass {
|
||||
explicit MachineFunctionPass(intptr_t ID) : FunctionPass(ID) {}
|
||||
explicit MachineFunctionPass(void *ID) : FunctionPass(ID) {}
|
||||
|
||||
/// createPrinterPass - Get a machine function printer pass.
|
||||
Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const;
|
||||
|
||||
/// runOnMachineFunction - This method must be overloaded to perform the
|
||||
/// desired machine code transformation or analysis.
|
||||
///
|
||||
@ -51,7 +48,11 @@ class MachineFunctionPass : public FunctionPass {
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
private:
|
||||
bool runOnFunction(Function &F);
|
||||
/// createPrinterPass - Get a machine function printer pass.
|
||||
virtual Pass *createPrinterPass(raw_ostream &O,
|
||||
const std::string &Banner) const;
|
||||
|
||||
virtual bool runOnFunction(Function &F);
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
@ -215,9 +215,6 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
bool isKill() const { return getOpcode() == TargetOpcode::KILL; }
|
||||
bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; }
|
||||
bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; }
|
||||
bool isExtractSubreg() const {
|
||||
return getOpcode() == TargetOpcode::EXTRACT_SUBREG;
|
||||
}
|
||||
bool isInsertSubreg() const {
|
||||
return getOpcode() == TargetOpcode::INSERT_SUBREG;
|
||||
}
|
||||
@ -227,7 +224,22 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
bool isRegSequence() const {
|
||||
return getOpcode() == TargetOpcode::REG_SEQUENCE;
|
||||
}
|
||||
|
||||
bool isCopy() const {
|
||||
return getOpcode() == TargetOpcode::COPY;
|
||||
}
|
||||
|
||||
/// isCopyLike - Return true if the instruction behaves like a copy.
|
||||
/// This does not include native copy instructions.
|
||||
bool isCopyLike() const {
|
||||
return isCopy() || isSubregToReg();
|
||||
}
|
||||
|
||||
/// isIdentityCopy - Return true is the instruction is an identity copy.
|
||||
bool isIdentityCopy() const {
|
||||
return isCopy() && getOperand(0).getReg() == getOperand(1).getReg() &&
|
||||
getOperand(0).getSubReg() == getOperand(1).getSubReg();
|
||||
}
|
||||
|
||||
/// readsRegister - Return true if the MachineInstr reads the specified
|
||||
/// register. If TargetRegisterInfo is passed, then it also checks if there
|
||||
/// is a read of a super-register.
|
||||
@ -339,6 +351,11 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
/// copyPredicates - Copies predicate operand(s) from MI.
|
||||
void copyPredicates(const MachineInstr *MI);
|
||||
|
||||
/// substituteRegister - Replace all occurrences of FromReg with ToReg:SubIdx,
|
||||
/// properly composing subreg indices where necessary.
|
||||
void substituteRegister(unsigned FromReg, unsigned ToReg, unsigned SubIdx,
|
||||
const TargetRegisterInfo &RegInfo);
|
||||
|
||||
/// addRegisterKilled - We have determined MI kills a register. Look for the
|
||||
/// operand that uses it and mark it as IsKill. If AddIfNotFound is true,
|
||||
/// add a implicit operand if it's not found. Returns true if the operand
|
||||
@ -359,6 +376,11 @@ class MachineInstr : public ilist_node<MachineInstr> {
|
||||
void addRegisterDefined(unsigned IncomingReg,
|
||||
const TargetRegisterInfo *RegInfo = 0);
|
||||
|
||||
/// setPhysRegsDeadExcept - Mark every physreg used by this instruction as dead
|
||||
/// except those in the UsedRegs list.
|
||||
void setPhysRegsDeadExcept(const SmallVectorImpl<unsigned> &UsedRegs,
|
||||
const TargetRegisterInfo &TRI);
|
||||
|
||||
/// isSafeToMove - Return true if it is safe to move this instruction. If
|
||||
/// SawStore is set to true, it means that there is a store (or call) between
|
||||
/// the instruction's location and its intended destination.
|
||||
|
@ -74,7 +74,7 @@ class MachineJumpTableInfo {
|
||||
JTEntryKind EntryKind;
|
||||
std::vector<MachineJumpTableEntry> JumpTables;
|
||||
public:
|
||||
MachineJumpTableInfo(JTEntryKind Kind): EntryKind(Kind) {}
|
||||
explicit MachineJumpTableInfo(JTEntryKind Kind): EntryKind(Kind) {}
|
||||
|
||||
JTEntryKind getEntryKind() const { return EntryKind; }
|
||||
|
||||
|
@ -64,13 +64,13 @@ class MachineLoopInfo : public MachineFunctionPass {
|
||||
void operator=(const MachineLoopInfo &); // do not implement
|
||||
MachineLoopInfo(const MachineLoopInfo &); // do not implement
|
||||
|
||||
LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; }
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
MachineLoopInfo() : MachineFunctionPass(&ID) {}
|
||||
|
||||
LoopInfoBase<MachineBasicBlock, MachineLoop>& getBase() { return LI; }
|
||||
|
||||
/// iterator/begin/end - The interface to the top-level loops in the current
|
||||
/// function.
|
||||
///
|
||||
|
@ -27,6 +27,7 @@ class MachineInstr;
|
||||
class MachineRegisterInfo;
|
||||
class MDNode;
|
||||
class TargetMachine;
|
||||
class TargetRegisterInfo;
|
||||
class raw_ostream;
|
||||
class MCSymbol;
|
||||
|
||||
@ -246,7 +247,20 @@ class MachineOperand {
|
||||
assert(isReg() && "Wrong MachineOperand accessor");
|
||||
SubReg = (unsigned char)subReg;
|
||||
}
|
||||
|
||||
|
||||
/// substVirtReg - Substitute the current register with the virtual
|
||||
/// subregister Reg:SubReg. Take any existing SubReg index into account,
|
||||
/// using TargetRegisterInfo to compose the subreg indices if necessary.
|
||||
/// Reg must be a virtual register, SubIdx can be 0.
|
||||
///
|
||||
void substVirtReg(unsigned Reg, unsigned SubIdx, const TargetRegisterInfo&);
|
||||
|
||||
/// substPhysReg - Substitute the current register with the physical register
|
||||
/// Reg, taking any existing SubReg into account. For instance,
|
||||
/// substPhysReg(%EAX) will change %reg1024:sub_8bit to %AL.
|
||||
///
|
||||
void substPhysReg(unsigned Reg, const TargetRegisterInfo&);
|
||||
|
||||
void setIsUse(bool Val = true) {
|
||||
assert(isReg() && "Wrong MachineOperand accessor");
|
||||
assert((Val || !isDebug()) && "Marking a debug operation as def");
|
||||
|
@ -35,7 +35,7 @@ class MachineRegisterInfo {
|
||||
/// RegClassVRegMap - This vector acts as a map from TargetRegisterClass to
|
||||
/// virtual registers. For each target register class, it keeps a list of
|
||||
/// virtual registers belonging to the class.
|
||||
std::vector<std::vector<unsigned> > RegClass2VRegMap;
|
||||
std::vector<unsigned> *RegClass2VRegMap;
|
||||
|
||||
/// RegAllocHints - This vector records register allocation hints for virtual
|
||||
/// registers. For each virtual register, it keeps a register and hint type
|
||||
@ -363,7 +363,18 @@ class MachineRegisterInfo {
|
||||
defusechain_iterator operator++(int) { // Postincrement
|
||||
defusechain_iterator tmp = *this; ++*this; return tmp;
|
||||
}
|
||||
|
||||
|
||||
/// skipInstruction - move forward until reaching a different instruction.
|
||||
/// Return the skipped instruction that is no longer pointed to, or NULL if
|
||||
/// already pointing to end().
|
||||
MachineInstr *skipInstruction() {
|
||||
if (!Op) return 0;
|
||||
MachineInstr *MI = Op->getParent();
|
||||
do ++*this;
|
||||
while (Op && Op->getParent() == MI);
|
||||
return MI;
|
||||
}
|
||||
|
||||
MachineOperand &getOperand() const {
|
||||
assert(Op && "Cannot dereference end iterator!");
|
||||
return *Op;
|
||||
|
@ -85,15 +85,10 @@ namespace llvm {
|
||||
///
|
||||
FunctionPass *createDeadMachineInstructionElimPass();
|
||||
|
||||
/// Creates a register allocator as the user specified on the command line.
|
||||
/// Creates a register allocator as the user specified on the command line, or
|
||||
/// picks one that matches OptLevel.
|
||||
///
|
||||
FunctionPass *createRegisterAllocator();
|
||||
|
||||
/// LocalRegisterAllocation Pass - This pass register allocates the input code
|
||||
/// a basic block at a time, yielding code better than the simple register
|
||||
/// allocator, but not as good as a global allocator.
|
||||
///
|
||||
FunctionPass *createLocalRegisterAllocator();
|
||||
FunctionPass *createRegisterAllocator(CodeGenOpt::Level OptLevel);
|
||||
|
||||
/// FastRegisterAllocation Pass - This pass register allocates as fast as
|
||||
/// possible. It is best suited for debug code where live ranges are short.
|
||||
@ -147,10 +142,6 @@ namespace llvm {
|
||||
/// headers to target specific alignment boundary.
|
||||
FunctionPass *createCodePlacementOptPass();
|
||||
|
||||
/// getRegisterAllocator - This creates an instance of the register allocator
|
||||
/// for the Sparc.
|
||||
FunctionPass *getRegisterAllocator(TargetMachine &T);
|
||||
|
||||
/// IntrinsicLowering Pass - Performs target-independent LLVM IR
|
||||
/// transformations for highly portable strategies.
|
||||
FunctionPass *createGCLoweringPass();
|
||||
|
94
include/llvm/CodeGen/PostRAHazardRecognizer.h
Normal file
94
include/llvm/CodeGen/PostRAHazardRecognizer.h
Normal file
@ -0,0 +1,94 @@
|
||||
//=- llvm/CodeGen/PostRAHazardRecognizer.h - Scheduling Support -*- C++ -*-=//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements the PostRAHazardRecognizer class, which
|
||||
// implements hazard-avoidance heuristics for scheduling, based on the
|
||||
// scheduling itineraries specified for the target.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H
|
||||
#define LLVM_CODEGEN_EXACTHAZARDRECOGNIZER_H
|
||||
|
||||
#include "llvm/CodeGen/ScheduleHazardRecognizer.h"
|
||||
#include "llvm/System/DataTypes.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class InstrItineraryData;
|
||||
class SUnit;
|
||||
|
||||
class PostRAHazardRecognizer : public ScheduleHazardRecognizer {
|
||||
// ScoreBoard to track function unit usage. ScoreBoard[0] is a
|
||||
// mask of the FUs in use in the cycle currently being
|
||||
// schedule. ScoreBoard[1] is a mask for the next cycle. The
|
||||
// ScoreBoard is used as a circular buffer with the current cycle
|
||||
// indicated by Head.
|
||||
class ScoreBoard {
|
||||
unsigned *Data;
|
||||
|
||||
// The maximum number of cycles monitored by the Scoreboard. This
|
||||
// value is determined based on the target itineraries to ensure
|
||||
// that all hazards can be tracked.
|
||||
size_t Depth;
|
||||
// Indices into the Scoreboard that represent the current cycle.
|
||||
size_t Head;
|
||||
public:
|
||||
ScoreBoard():Data(NULL), Depth(0), Head(0) { }
|
||||
~ScoreBoard() {
|
||||
delete[] Data;
|
||||
}
|
||||
|
||||
size_t getDepth() const { return Depth; }
|
||||
unsigned& operator[](size_t idx) const {
|
||||
assert(Depth && "ScoreBoard was not initialized properly!");
|
||||
|
||||
return Data[(Head + idx) % Depth];
|
||||
}
|
||||
|
||||
void reset(size_t d = 1) {
|
||||
if (Data == NULL) {
|
||||
Depth = d;
|
||||
Data = new unsigned[Depth];
|
||||
}
|
||||
|
||||
memset(Data, 0, Depth * sizeof(Data[0]));
|
||||
Head = 0;
|
||||
}
|
||||
|
||||
void advance() {
|
||||
Head = (Head + 1) % Depth;
|
||||
}
|
||||
|
||||
// Print the scoreboard.
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
// Itinerary data for the target.
|
||||
const InstrItineraryData &ItinData;
|
||||
|
||||
ScoreBoard ReservedScoreboard;
|
||||
ScoreBoard RequiredScoreboard;
|
||||
|
||||
public:
|
||||
PostRAHazardRecognizer(const InstrItineraryData &ItinData);
|
||||
|
||||
virtual HazardType getHazardType(SUnit *SU);
|
||||
virtual void Reset();
|
||||
virtual void EmitInstruction(SUnit *SU);
|
||||
virtual void AdvanceCycle();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -25,6 +25,9 @@ namespace llvm {
|
||||
class RegallocQuery;
|
||||
class AnalysisUsage;
|
||||
class MachineInstr;
|
||||
class TargetRegisterInfo;
|
||||
class TargetRegisterClass;
|
||||
class TargetInstrInfo;
|
||||
|
||||
/// An abstract interface for register coalescers. Coalescers must
|
||||
/// implement this interface to be part of the coalescer analysis
|
||||
@ -141,6 +144,93 @@ namespace llvm {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// CoalescerPair - A helper class for register coalescers. When deciding if
|
||||
/// two registers can be coalesced, CoalescerPair can determine if a copy
|
||||
/// instruction would become an identity copy after coalescing.
|
||||
class CoalescerPair {
|
||||
const TargetInstrInfo &tii_;
|
||||
const TargetRegisterInfo &tri_;
|
||||
|
||||
/// dstReg_ - The register that will be left after coalescing. It can be a
|
||||
/// virtual or physical register.
|
||||
unsigned dstReg_;
|
||||
|
||||
/// srcReg_ - the virtual register that will be coalesced into dstReg.
|
||||
unsigned srcReg_;
|
||||
|
||||
/// subReg_ - The subregister index of srcReg in dstReg_. It is possible the
|
||||
/// coalesce srcReg_ into a subreg of the larger dstReg_ when dstReg_ is a
|
||||
/// virtual register.
|
||||
unsigned subIdx_;
|
||||
|
||||
/// partial_ - True when the original copy was a partial subregister copy.
|
||||
bool partial_;
|
||||
|
||||
/// crossClass_ - True when both regs are virtual, and newRC is constrained.
|
||||
bool crossClass_;
|
||||
|
||||
/// flipped_ - True when DstReg and SrcReg are reversed from the oriignal copy
|
||||
/// instruction.
|
||||
bool flipped_;
|
||||
|
||||
/// newRC_ - The register class of the coalesced register, or NULL if dstReg_
|
||||
/// is a physreg.
|
||||
const TargetRegisterClass *newRC_;
|
||||
|
||||
/// compose - Compose subreg indices a and b, either may be 0.
|
||||
unsigned compose(unsigned, unsigned) const;
|
||||
|
||||
/// isMoveInstr - Return true if MI is a move or subreg instruction.
|
||||
bool isMoveInstr(const MachineInstr *MI, unsigned &Src, unsigned &Dst,
|
||||
unsigned &SrcSub, unsigned &DstSub) const;
|
||||
|
||||
public:
|
||||
CoalescerPair(const TargetInstrInfo &tii, const TargetRegisterInfo &tri)
|
||||
: tii_(tii), tri_(tri), dstReg_(0), srcReg_(0), subIdx_(0),
|
||||
partial_(false), crossClass_(false), flipped_(false), newRC_(0) {}
|
||||
|
||||
/// setRegisters - set registers to match the copy instruction MI. Return
|
||||
/// false if MI is not a coalescable copy instruction.
|
||||
bool setRegisters(const MachineInstr*);
|
||||
|
||||
/// flip - Swap srcReg_ and dstReg_. Return false if swapping is impossible
|
||||
/// because dstReg_ is a physical register, or subIdx_ is set.
|
||||
bool flip();
|
||||
|
||||
/// isCoalescable - Return true if MI is a copy instruction that will become
|
||||
/// an identity copy after coalescing.
|
||||
bool isCoalescable(const MachineInstr*) const;
|
||||
|
||||
/// isPhys - Return true if DstReg is a physical register.
|
||||
bool isPhys() const { return !newRC_; }
|
||||
|
||||
/// isPartial - Return true if the original copy instruction did not copy the
|
||||
/// full register, but was a subreg operation.
|
||||
bool isPartial() const { return partial_; }
|
||||
|
||||
/// isCrossClass - Return true if DstReg is virtual and NewRC is a smaller register class than DstReg's.
|
||||
bool isCrossClass() const { return crossClass_; }
|
||||
|
||||
/// isFlipped - Return true when getSrcReg is the register being defined by
|
||||
/// the original copy instruction.
|
||||
bool isFlipped() const { return flipped_; }
|
||||
|
||||
/// getDstReg - Return the register (virtual or physical) that will remain
|
||||
/// after coalescing.
|
||||
unsigned getDstReg() const { return dstReg_; }
|
||||
|
||||
/// getSrcReg - Return the virtual register that will be coalesced away.
|
||||
unsigned getSrcReg() const { return srcReg_; }
|
||||
|
||||
/// getSubIdx - Return the subregister index in DstReg that SrcReg will be
|
||||
/// coalesced into, or 0.
|
||||
unsigned getSubIdx() const { return subIdx_; }
|
||||
|
||||
/// getNewRC - Return the register class of the coalesced register.
|
||||
const TargetRegisterClass *getNewRC() const { return newRC_; }
|
||||
};
|
||||
}
|
||||
|
||||
// Because of the way .a files work, we must force the SimpleRC
|
||||
|
@ -98,6 +98,10 @@ class RegScavenger {
|
||||
/// getRegsUsed - return all registers currently in use in used.
|
||||
void getRegsUsed(BitVector &used, bool includeReserved);
|
||||
|
||||
/// getRegsAvailable - Return all available registers in the register class
|
||||
/// in Mask.
|
||||
void getRegsAvailable(const TargetRegisterClass *RC, BitVector &Mask);
|
||||
|
||||
/// FindUnusedReg - Find a unused register of the specified register class.
|
||||
/// Return 0 if none is found.
|
||||
unsigned FindUnusedReg(const TargetRegisterClass *RegClass) const;
|
||||
@ -147,7 +151,12 @@ class RegScavenger {
|
||||
/// Add Reg and its aliases to BV.
|
||||
void addRegWithAliases(BitVector &BV, unsigned Reg);
|
||||
|
||||
unsigned findSurvivorReg(MachineBasicBlock::iterator MI,
|
||||
/// findSurvivorReg - Return the candidate register that is unused for the
|
||||
/// longest after StartMI. UseMI is set to the instruction where the search
|
||||
/// stopped.
|
||||
///
|
||||
/// No more than InstrLimit instructions are inspected.
|
||||
unsigned findSurvivorReg(MachineBasicBlock::iterator StartMI,
|
||||
BitVector &Candidates,
|
||||
unsigned InstrLimit,
|
||||
MachineBasicBlock::iterator &UseMI);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user