Import LLVM, at r72995.
We should now have support for #pragma weak.
This commit is contained in:
parent
68eb509bdc
commit
f4fe016fa1
@ -58,13 +58,22 @@ endif( MSVC )
|
||||
option(LLVM_ENABLE_THREADS "Use threads if available." ON)
|
||||
|
||||
if( uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" )
|
||||
option(LLVM_ENABLE_ASSERTS "Enable asserts" OFF)
|
||||
option(LLVM_ENABLE_ASSERTIONS "Enable assertions" OFF)
|
||||
else()
|
||||
option(LLVM_ENABLE_ASSERTS "Enable asserts" ON)
|
||||
option(LLVM_ENABLE_ASSERTIONS "Enable assertions" ON)
|
||||
endif()
|
||||
|
||||
if( LLVM_ENABLE_ASSERTS )
|
||||
add_definitions( -D_DEBUG -UNDEBUG )
|
||||
if( LLVM_ENABLE_ASSERTIONS )
|
||||
add_definitions( -D_DEBUG )
|
||||
# On Release builds cmake automatically defines NDEBUG, so we
|
||||
# explicitly undefine it:
|
||||
if( uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" )
|
||||
add_definitions( -UNDEBUG )
|
||||
endif()
|
||||
else()
|
||||
if( NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE" )
|
||||
add_definitions( -DNDEBUG )
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if( LLVM_TARGETS_TO_BUILD STREQUAL "all" )
|
||||
@ -81,6 +90,24 @@ endforeach(c)
|
||||
|
||||
set(llvm_builded_incs_dir ${LLVM_BINARY_DIR}/include/llvm)
|
||||
|
||||
# The USE_EXPLICIT_DEPENDENCIES variable will be TRUE to indicate that
|
||||
# we should use the library dependencies explicitly specified in the
|
||||
# CMakeLists.txt files rather than those determined by
|
||||
# llvm-config. This value must be true for non-make and IDE
|
||||
# generators.
|
||||
if (MSVC_IDE)
|
||||
set(DEFAULT_USE_EXPLICIT_DEPENDENCIES ON)
|
||||
elseif (XCODE)
|
||||
set(DEFAULT_USE_EXPLICIT_DEPENDENCIES ON)
|
||||
else ()
|
||||
set(DEFAULT_USE_EXPLICIT_DEPENDENCIES OFF)
|
||||
endif ()
|
||||
|
||||
option(USE_EXPLICIT_DEPENDENCIES
|
||||
"Use explicit dependencies instead of llvm-config"
|
||||
${DEFAULT_USE_EXPLICIT_DEPENDENCIES})
|
||||
mark_as_advanced(USE_EXPLICIT_DEPENDENCIES)
|
||||
|
||||
# Add path for custom modules
|
||||
set(CMAKE_MODULE_PATH
|
||||
${CMAKE_MODULE_PATH}
|
||||
@ -123,11 +150,13 @@ include(config-ix)
|
||||
|
||||
option(LLVM_ENABLE_PIC "Build Position-Independent Code" OFF)
|
||||
|
||||
set(ENABLE_PIC 0)
|
||||
if( LLVM_ENABLE_PIC )
|
||||
if( SUPPORTS_FPIC_FLAG )
|
||||
message(STATUS "Building with -fPIC")
|
||||
add_llvm_definitions(-fPIC)
|
||||
else( SUPPORTS_FPIC_FLAG )
|
||||
set(ENABLE_PIC 1)
|
||||
else( SUPPORTS_FPIC_FLAG )
|
||||
message(STATUS "Warning: -fPIC not supported.")
|
||||
endif()
|
||||
endif()
|
||||
|
@ -1066,7 +1066,7 @@ all-local:: $(LibName.O)
|
||||
|
||||
$(LibName.O): $(ObjectsO) $(LibDir)/.dir
|
||||
$(Echo) Linking $(BuildMode) Object Library $(notdir $@)
|
||||
$(Verb) $(Relink) -Wl,-r -nodefaultlibs -nostdlib -nostartfiles -o $@ $(ObjectsO)
|
||||
$(Verb) $(Relink) -r -nodefaultlibs -nostdlib -nostartfiles -o $@ $(ObjectsO)
|
||||
|
||||
clean-local::
|
||||
ifneq ($(strip $(LibName.O)),)
|
||||
|
@ -279,7 +279,7 @@ dnl===-----------------------------------------------------------------------===
|
||||
|
||||
dnl --enable-optimized : check whether they want to do an optimized build:
|
||||
AC_ARG_ENABLE(optimized, AS_HELP_STRING(
|
||||
[--enable-optimized,Compile with optimizations enabled (default is NO)]),,enableval=$optimize)
|
||||
--enable-optimized,[Compile with optimizations enabled (default is NO)]),,enableval=$optimize)
|
||||
if test ${enableval} = "no" ; then
|
||||
AC_SUBST(ENABLE_OPTIMIZED,[[]])
|
||||
else
|
||||
@ -288,7 +288,7 @@ fi
|
||||
|
||||
dnl --enable-profiling : check whether they want to do a profile build:
|
||||
AC_ARG_ENABLE(profiling, AS_HELP_STRING(
|
||||
[--enable-profiling,Compile with profiling enabled (default is NO)]),,enableval="no")
|
||||
--enable-profiling,[Compile with profiling enabled (default is NO)]),,enableval="no")
|
||||
if test ${enableval} = "no" ; then
|
||||
AC_SUBST(ENABLE_PROFILING,[[]])
|
||||
else
|
||||
@ -297,7 +297,7 @@ fi
|
||||
|
||||
dnl --enable-assertions : check whether they want to turn on assertions or not:
|
||||
AC_ARG_ENABLE(assertions,AS_HELP_STRING(
|
||||
[--enable-assertions,Compile with assertion checks enabled (default is YES)]),, enableval="yes")
|
||||
--enable-assertions,[Compile with assertion checks enabled (default is YES)]),, enableval="yes")
|
||||
if test ${enableval} = "yes" ; then
|
||||
AC_SUBST(DISABLE_ASSERTIONS,[[]])
|
||||
else
|
||||
@ -306,7 +306,7 @@ fi
|
||||
|
||||
dnl --enable-expensive-checks : check whether they want to turn on expensive debug checks:
|
||||
AC_ARG_ENABLE(expensive-checks,AS_HELP_STRING(
|
||||
[--enable-expensive-checks,Compile with expensive debug checks enabled (default is NO)]),, enableval="no")
|
||||
--enable-expensive-checks,[Compile with expensive debug checks enabled (default is NO)]),, enableval="no")
|
||||
if test ${enableval} = "yes" ; then
|
||||
AC_SUBST(ENABLE_EXPENSIVE_CHECKS,[[ENABLE_EXPENSIVE_CHECKS=1]])
|
||||
AC_SUBST(EXPENSIVE_CHECKS,[[yes]])
|
||||
@ -317,7 +317,7 @@ fi
|
||||
|
||||
dnl --enable-debug-runtime : should runtime libraries have debug symbols?
|
||||
AC_ARG_ENABLE(debug-runtime,
|
||||
AS_HELP_STRING([--enable-debug-runtime,Build runtime libs with debug symbols (default is NO)]),,enableval=no)
|
||||
AS_HELP_STRING(--enable-debug-runtime,[Build runtime libs with debug symbols (default is NO)]),,enableval=no)
|
||||
if test ${enableval} = "no" ; then
|
||||
AC_SUBST(DEBUG_RUNTIME,[[]])
|
||||
else
|
||||
@ -553,6 +553,16 @@ if test "x$WITH_BINUTILS_INCDIR" != xdefault ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
dnl --enable-libffi : check whether the user wants to turn off libffi:
|
||||
AC_ARG_ENABLE(libffi,AS_HELP_STRING(
|
||||
--enable-libffi,[Check for the presence of libffi (default is YES)]),,
|
||||
enableval=yes)
|
||||
case "$enableval" in
|
||||
yes) llvm_cv_enable_libffi="yes" ;;
|
||||
no) llvm_cv_enable_libffi="no" ;;
|
||||
*) AC_MSG_ERROR([Invalid setting for --enable-libffi. Use "yes" or "no"]) ;;
|
||||
esac
|
||||
|
||||
dnl===-----------------------------------------------------------------------===
|
||||
dnl===
|
||||
dnl=== SECTION 4: Check for programs we need and that they are the right version
|
||||
@ -769,9 +779,11 @@ AC_SEARCH_LIBS(dlopen,dl,AC_DEFINE([HAVE_DLOPEN],[1],
|
||||
AC_MSG_WARN([dlopen() not found - disabling plugin support]))
|
||||
|
||||
dnl libffi is optional; used to call external functions from the interpreter
|
||||
AC_SEARCH_LIBS(ffi_call,ffi,AC_DEFINE([HAVE_FFI_CALL],[1],
|
||||
[Define if libffi is available on this platform.]),
|
||||
AC_MSG_WARN([libffi not found - disabling external calls from interpreter]))
|
||||
if test "$llvm_cv_enable_libffi" = "yes" ; then
|
||||
AC_SEARCH_LIBS(ffi_call,ffi,AC_DEFINE([HAVE_FFI_CALL],[1],
|
||||
[Define if libffi is available on this platform.]),
|
||||
AC_MSG_WARN([libffi not found - disabling external calls from interpreter]))
|
||||
fi
|
||||
|
||||
dnl mallinfo is optional; the code can compile (minus features) without it
|
||||
AC_SEARCH_LIBS(mallinfo,malloc,AC_DEFINE([HAVE_MALLINFO],[1],
|
||||
@ -836,7 +848,9 @@ else
|
||||
fi
|
||||
|
||||
dnl Try to find ffi.h.
|
||||
AC_CHECK_HEADERS([ffi.h ffi/ffi.h])
|
||||
if test "$llvm_cv_enable_libffi" = "yes" ; then
|
||||
AC_CHECK_HEADERS([ffi.h ffi/ffi.h])
|
||||
fi
|
||||
|
||||
dnl===-----------------------------------------------------------------------===
|
||||
dnl===
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
# include checks
|
||||
include(CheckIncludeFile)
|
||||
check_include_file(alloca.h HAVE_ALLOCA_H)
|
||||
check_include_file(argz.h HAVE_ARGZ_H)
|
||||
check_include_file(assert.h HAVE_ASSERT_H)
|
||||
check_include_file(dirent.h HAVE_DIRENT_H)
|
||||
@ -34,6 +35,7 @@ check_include_file(sys/resource.h HAVE_SYS_RESOURCE_H)
|
||||
check_include_file(sys/stat.h HAVE_SYS_STAT_H)
|
||||
check_include_file(sys/time.h HAVE_SYS_TIME_H)
|
||||
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
|
||||
check_include_file(sys/wait.h HAVE_SYS_WAIT_H)
|
||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||
check_include_file(unistd.h HAVE_UNISTD_H)
|
||||
check_include_file(utime.h HAVE_UTIME_H)
|
||||
@ -47,6 +49,7 @@ check_library_exists(dl dlopen "" HAVE_LIBDL)
|
||||
# function checks
|
||||
include(CheckSymbolExists)
|
||||
include(CheckFunctionExists)
|
||||
check_symbol_exists(alloca alloca.h HAVE_ALLOCA)
|
||||
check_symbol_exists(getpagesize unistd.h HAVE_GETPAGESIZE)
|
||||
check_symbol_exists(getrusage sys/resource.h HAVE_GETRUSAGE)
|
||||
check_symbol_exists(setrlimit sys/resource.h HAVE_SETRLIMIT)
|
||||
@ -58,6 +61,8 @@ check_symbol_exists(isnan math.h HAVE_ISNAN_IN_MATH_H)
|
||||
check_symbol_exists(ceilf math.h HAVE_CEILF)
|
||||
check_symbol_exists(floorf math.h HAVE_FLOORF)
|
||||
check_symbol_exists(mallinfo malloc.h HAVE_MALLINFO)
|
||||
check_symbol_exists(malloc_zone_statistics malloc/malloc.h
|
||||
HAVE_MALLOC_ZONE_STATISTICS)
|
||||
check_symbol_exists(pthread_mutex_lock pthread.h HAVE_PTHREAD_MUTEX_LOCK)
|
||||
check_symbol_exists(strtoll stdlib.h HAVE_STRTOLL)
|
||||
|
||||
|
@ -26,11 +26,11 @@ macro(add_llvm_executable name)
|
||||
if( LLVM_LINK_COMPONENTS )
|
||||
llvm_config(${name} ${LLVM_LINK_COMPONENTS})
|
||||
endif( LLVM_LINK_COMPONENTS )
|
||||
if( MSVC )
|
||||
if( USE_EXPLICIT_DEPENDENCIES )
|
||||
target_link_libraries(${name} ${llvm_libs})
|
||||
else( MSVC )
|
||||
else( )
|
||||
add_dependencies(${name} llvm-config.target)
|
||||
endif( MSVC )
|
||||
endif( )
|
||||
get_system_libs(llvm_system_libs)
|
||||
if( llvm_system_libs )
|
||||
target_link_libraries(${name} ${llvm_system_libs})
|
||||
|
@ -1,18 +1,18 @@
|
||||
include(LLVMProcessSources)
|
||||
|
||||
macro(target_name_of_partially_linked_object lib var)
|
||||
if( MSVC )
|
||||
if( USE_EXPLICIT_DEPENDENCIES )
|
||||
set(${var} ${lib})
|
||||
else( MSVC )
|
||||
else( )
|
||||
set(${var} ${lib}_pll)
|
||||
endif( MSVC )
|
||||
endif( )
|
||||
endmacro(target_name_of_partially_linked_object lib var)
|
||||
|
||||
|
||||
macro(add_partially_linked_object lib)
|
||||
if( MSVC )
|
||||
if( USE_EXPLICIT_DEPENDENCIES )
|
||||
add_llvm_library( ${lib} ${ARGN})
|
||||
else( MSVC )
|
||||
else( )
|
||||
set(pll ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}/${CMAKE_CFG_INTDIR}/${lib}.o)
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/temp_lib)
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/temp_lib)
|
||||
@ -36,7 +36,7 @@ macro(add_partially_linked_object lib)
|
||||
add_custom_target(${tnplo} ALL DEPENDS ${pll})
|
||||
set( llvm_libs ${llvm_libs} ${pll} PARENT_SCOPE)
|
||||
set( llvm_lib_targets ${llvm_lib_targets} ${tnplo} PARENT_SCOPE )
|
||||
endif( MSVC )
|
||||
endif( )
|
||||
install(FILES ${pll}
|
||||
DESTINATION lib)
|
||||
endmacro(add_partially_linked_object lib)
|
||||
|
@ -21,36 +21,40 @@ endfunction(get_system_libs)
|
||||
|
||||
macro(llvm_config executable)
|
||||
# extra args is the list of link components.
|
||||
if( MSVC )
|
||||
msvc_llvm_config(${executable} ${ARGN})
|
||||
else( MSVC )
|
||||
if( USE_EXPLICIT_DEPENDENCIES )
|
||||
explicit_llvm_config(${executable} ${ARGN})
|
||||
else( )
|
||||
nix_llvm_config(${executable} ${ARGN})
|
||||
endif( MSVC )
|
||||
endif( )
|
||||
endmacro(llvm_config)
|
||||
|
||||
|
||||
function(msvc_llvm_config executable)
|
||||
function(explicit_llvm_config executable)
|
||||
set( link_components ${ARGN} )
|
||||
if( CMAKE_CL_64 )
|
||||
set(include_lflag "/INCLUDE:")
|
||||
else( CMAKE_CL_64 )
|
||||
set(include_lflag "/INCLUDE:_")
|
||||
endif()
|
||||
foreach(c ${link_components})
|
||||
if( c STREQUAL "jit" )
|
||||
set(lfgs "${lfgs} ${include_lflag}X86TargetMachineModule")
|
||||
endif( c STREQUAL "jit" )
|
||||
list(FIND LLVM_TARGETS_TO_BUILD ${c} idx)
|
||||
if( NOT idx LESS 0 )
|
||||
set(lfgs "${lfgs} ${include_lflag}${c}TargetMachineModule")
|
||||
list(FIND LLVM_ASMPRINTERS_FORCE_LINK ${c} idx)
|
||||
if( NOT idx LESS 0 )
|
||||
set(lfgs "${lfgs} ${include_lflag}${c}AsmPrinterForceLink")
|
||||
endif()
|
||||
endif()
|
||||
endforeach(c)
|
||||
|
||||
msvc_map_components_to_libraries(LIBRARIES ${link_components})
|
||||
set(lfgs)
|
||||
if (MSVC)
|
||||
if( CMAKE_CL_64 )
|
||||
set(include_lflag "/INCLUDE:")
|
||||
else( CMAKE_CL_64 )
|
||||
set(include_lflag "/INCLUDE:_")
|
||||
endif()
|
||||
foreach(c ${link_components})
|
||||
if( c STREQUAL "jit" )
|
||||
set(lfgs "${lfgs} ${include_lflag}X86TargetMachineModule")
|
||||
endif( c STREQUAL "jit" )
|
||||
list(FIND LLVM_TARGETS_TO_BUILD ${c} idx)
|
||||
if( NOT idx LESS 0 )
|
||||
set(lfgs "${lfgs} ${include_lflag}${c}TargetMachineModule")
|
||||
list(FIND LLVM_ASMPRINTERS_FORCE_LINK ${c} idx)
|
||||
if( NOT idx LESS 0 )
|
||||
set(lfgs "${lfgs} ${include_lflag}${c}AsmPrinterForceLink")
|
||||
endif()
|
||||
endif()
|
||||
endforeach(c)
|
||||
endif ()
|
||||
|
||||
explicit_map_components_to_libraries(LIBRARIES ${link_components})
|
||||
target_link_libraries(${executable} ${LIBRARIES})
|
||||
|
||||
if( lfgs )
|
||||
@ -58,10 +62,10 @@ function(msvc_llvm_config executable)
|
||||
PROPERTIES
|
||||
LINK_FLAGS ${lfgs})
|
||||
endif()
|
||||
endfunction(msvc_llvm_config)
|
||||
endfunction(explicit_llvm_config)
|
||||
|
||||
|
||||
function(msvc_map_components_to_libraries out_libs)
|
||||
function(explicit_map_components_to_libraries out_libs)
|
||||
set( link_components ${ARGN} )
|
||||
foreach(c ${link_components})
|
||||
# add codegen/asmprinter
|
||||
@ -121,7 +125,7 @@ function(msvc_map_components_to_libraries out_libs)
|
||||
endwhile( ${curr_idx} LESS ${lst_size} )
|
||||
list(REMOVE_DUPLICATES result)
|
||||
set(${out_libs} ${result} PARENT_SCOPE)
|
||||
endfunction(msvc_map_components_to_libraries)
|
||||
endfunction(explicit_map_components_to_libraries)
|
||||
|
||||
|
||||
macro(nix_llvm_config executable)
|
||||
|
83
configure
vendored
83
configure
vendored
@ -1533,12 +1533,15 @@ if test -n "$ac_init_help"; then
|
||||
Optional Features:
|
||||
--disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
|
||||
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
|
||||
--enable-optimized
|
||||
--enable-profiling
|
||||
--enable-assertions
|
||||
--enable-optimized Compile with optimizations enabled (default is NO)
|
||||
--enable-profiling Compile with profiling enabled (default is NO)
|
||||
--enable-assertions Compile with assertion checks enabled (default is
|
||||
YES)
|
||||
--enable-expensive-checks
|
||||
|
||||
--enable-debug-runtime
|
||||
Compile with expensive debug checks enabled (default
|
||||
is NO)
|
||||
--enable-debug-runtime Build runtime libs with debug symbols (default is
|
||||
NO)
|
||||
--enable-jit Enable Just In Time Compiling (default is YES)
|
||||
--enable-doxygen Build doxygen documentation (default is NO)
|
||||
--enable-threads Use threads if available (default is YES)
|
||||
@ -1550,6 +1553,7 @@ Optional Features:
|
||||
%a (default is YES)
|
||||
--enable-bindings Build specific language bindings:
|
||||
all,auto,none,{binding-name} (default=auto)
|
||||
--enable-libffi Check for the presence of libffi (default is YES)
|
||||
--enable-ltdl-install install libltdl
|
||||
--enable-shared[=PKGS] build shared libraries
|
||||
[default=yes]
|
||||
@ -5111,6 +5115,21 @@ echo "$as_me: error: Invalid path to directory containing plugin-api.h." >&2;}
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check whether --enable-libffi was given.
|
||||
if test "${enable_libffi+set}" = set; then
|
||||
enableval=$enable_libffi;
|
||||
else
|
||||
enableval=yes
|
||||
fi
|
||||
|
||||
case "$enableval" in
|
||||
yes) llvm_cv_enable_libffi="yes" ;;
|
||||
no) llvm_cv_enable_libffi="no" ;;
|
||||
*) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-libffi. Use \"yes\" or \"no\"" >&5
|
||||
echo "$as_me: error: Invalid setting for --enable-libffi. Use \"yes\" or \"no\"" >&2;}
|
||||
{ (exit 1); exit 1; }; } ;;
|
||||
esac
|
||||
|
||||
|
||||
ac_ext=c
|
||||
ac_cpp='$CPP $CPPFLAGS'
|
||||
@ -10575,7 +10594,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 10578 "configure"
|
||||
#line 10597 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -12719,7 +12738,7 @@ ia64-*-hpux*)
|
||||
;;
|
||||
*-*-irix6*)
|
||||
# Find out which ABI we are using.
|
||||
echo '#line 12722 "configure"' > conftest.$ac_ext
|
||||
echo '#line 12741 "configure"' > conftest.$ac_ext
|
||||
if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
|
||||
(eval $ac_compile) 2>&5
|
||||
ac_status=$?
|
||||
@ -14437,11 +14456,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:14440: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:14459: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:14444: \$? = $ac_status" >&5
|
||||
echo "$as_me:14463: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -14705,11 +14724,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:14708: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:14727: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:14712: \$? = $ac_status" >&5
|
||||
echo "$as_me:14731: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -14809,11 +14828,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:14812: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:14831: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:14816: \$? = $ac_status" >&5
|
||||
echo "$as_me:14835: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@ -17261,7 +17280,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 17264 "configure"
|
||||
#line 17283 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -17361,7 +17380,7 @@ else
|
||||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 17364 "configure"
|
||||
#line 17383 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
@ -19729,11 +19748,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:19732: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:19751: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:19736: \$? = $ac_status" >&5
|
||||
echo "$as_me:19755: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -19833,11 +19852,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:19836: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:19855: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:19840: \$? = $ac_status" >&5
|
||||
echo "$as_me:19859: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@ -21403,11 +21422,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:21406: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:21425: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:21410: \$? = $ac_status" >&5
|
||||
echo "$as_me:21429: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -21507,11 +21526,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:21510: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:21529: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:21514: \$? = $ac_status" >&5
|
||||
echo "$as_me:21533: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@ -23742,11 +23761,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:23745: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:23764: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:23749: \$? = $ac_status" >&5
|
||||
echo "$as_me:23768: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -24010,11 +24029,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:24013: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:24032: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>conftest.err)
|
||||
ac_status=$?
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:24017: \$? = $ac_status" >&5
|
||||
echo "$as_me:24036: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s "$ac_outfile"; then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
# So say no if there are warnings other than the usual output.
|
||||
@ -24114,11 +24133,11 @@ else
|
||||
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
|
||||
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
|
||||
-e 's:$: $lt_compiler_flag:'`
|
||||
(eval echo "\"\$as_me:24117: $lt_compile\"" >&5)
|
||||
(eval echo "\"\$as_me:24136: $lt_compile\"" >&5)
|
||||
(eval "$lt_compile" 2>out/conftest.err)
|
||||
ac_status=$?
|
||||
cat out/conftest.err >&5
|
||||
echo "$as_me:24121: \$? = $ac_status" >&5
|
||||
echo "$as_me:24140: \$? = $ac_status" >&5
|
||||
if (exit $ac_status) && test -s out/conftest2.$ac_objext
|
||||
then
|
||||
# The compiler can only warn and ignore the option if not recognized
|
||||
@ -27473,7 +27492,8 @@ echo "$as_me: WARNING: dlopen() not found - disabling plugin support" >&2;}
|
||||
fi
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for library containing ffi_call" >&5
|
||||
if test "$llvm_cv_enable_libffi" = "yes" ; then
|
||||
{ echo "$as_me:$LINENO: checking for library containing ffi_call" >&5
|
||||
echo $ECHO_N "checking for library containing ffi_call... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_search_ffi_call+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
@ -27579,6 +27599,7 @@ else
|
||||
echo "$as_me: WARNING: libffi not found - disabling external calls from interpreter" >&2;}
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for library containing mallinfo" >&5
|
||||
echo $ECHO_N "checking for library containing mallinfo... $ECHO_C" >&6; }
|
||||
@ -29824,6 +29845,7 @@ else
|
||||
|
||||
fi
|
||||
|
||||
if test "$llvm_cv_enable_libffi" = "yes" ; then
|
||||
|
||||
|
||||
for ac_header in ffi.h ffi/ffi.h
|
||||
@ -29994,6 +30016,7 @@ fi
|
||||
|
||||
done
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
@ -248,8 +248,8 @@
|
||||
<dt><b>LLVM_ENABLE_THREADS</b>:BOOL</dt>
|
||||
<dd>Build with threads support, if available. Defaults to ON.</dd>
|
||||
|
||||
<dt><b>LLVM_ENABLE_ASSERTS</b>:BOOL</dt>
|
||||
<dd>Enables code asserts. Defaults to ON if and only if
|
||||
<dt><b>LLVM_ENABLE_ASSERTIONS</b>:BOOL</dt>
|
||||
<dd>Enables code assertions. Defaults to ON if and only if
|
||||
CMAKE_BUILD_TYPE is <i>Release</i>.</dd>
|
||||
|
||||
<dt><b>LLVM_ENABLE_PIC</b>:BOOL</dt>
|
||||
|
@ -153,9 +153,18 @@ $ llvm-gcc -use-gold-plugin a.o b.o -o main # <-- link with LLVMgold plugin
|
||||
<pre class="doc_code">
|
||||
export CC="$PREFIX/bin/llvm-gcc -use-gold-plugin"
|
||||
export CXX="$PREFIX/bin/llvm-g++ -use-gold-plugin"
|
||||
export AR="$PREFIX/bin/ar --plugin libLLVMgold.so"
|
||||
export NM="$PREFIX/bin/nm --plugin libLLVMgold.so"
|
||||
export AR="$PREFIX/bin/ar"
|
||||
export NM="$PREFIX/bin/nm"
|
||||
export RANLIB=/bin/true #ranlib is not needed, and doesn't support .bc files in .a
|
||||
export CFLAGS="-O4"
|
||||
</pre>
|
||||
</li>
|
||||
<li>Or you can just set your path:
|
||||
<pre class="doc_code">
|
||||
export PATH="$PREFIX/bin:$PATH"
|
||||
export CC="llvm-gcc -use-gold-plugin"
|
||||
export CXX="llvm-g++ -use-gold-plugin"
|
||||
export RANLIB=/bin/true
|
||||
export CFLAGS="-O4"
|
||||
</pre>
|
||||
</li>
|
||||
|
@ -89,8 +89,11 @@
|
||||
<li><a href="#binaryops">Binary Operations</a>
|
||||
<ol>
|
||||
<li><a href="#i_add">'<tt>add</tt>' Instruction</a></li>
|
||||
<li><a href="#i_fadd">'<tt>fadd</tt>' Instruction</a></li>
|
||||
<li><a href="#i_sub">'<tt>sub</tt>' Instruction</a></li>
|
||||
<li><a href="#i_fsub">'<tt>fsub</tt>' Instruction</a></li>
|
||||
<li><a href="#i_mul">'<tt>mul</tt>' Instruction</a></li>
|
||||
<li><a href="#i_fmul">'<tt>fmul</tt>' Instruction</a></li>
|
||||
<li><a href="#i_udiv">'<tt>udiv</tt>' Instruction</a></li>
|
||||
<li><a href="#i_sdiv">'<tt>sdiv</tt>' Instruction</a></li>
|
||||
<li><a href="#i_fdiv">'<tt>fdiv</tt>' Instruction</a></li>
|
||||
@ -2503,16 +2506,15 @@ The result value has the same type as its operands.</p>
|
||||
<h5>Arguments:</h5>
|
||||
|
||||
<p>The two arguments to the '<tt>add</tt>' instruction must be <a
|
||||
href="#t_integer">integer</a>, <a href="#t_floating">floating point</a>, or
|
||||
<a href="#t_vector">vector</a> values. Both arguments must have identical
|
||||
types.</p>
|
||||
href="#t_integer">integer</a> or
|
||||
<a href="#t_vector">vector</a> of integer values. Both arguments must
|
||||
have identical types.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
|
||||
<p>The value produced is the integer or floating point sum of the two
|
||||
operands.</p>
|
||||
<p>The value produced is the integer sum of the two operands.</p>
|
||||
|
||||
<p>If an integer sum has unsigned overflow, the result returned is the
|
||||
<p>If the sum has unsigned overflow, the result returned is the
|
||||
mathematical result modulo 2<sup>n</sup>, where n is the bit width of
|
||||
the result.</p>
|
||||
|
||||
@ -2526,6 +2528,39 @@ instruction is appropriate for both signed and unsigned integers.</p>
|
||||
</pre>
|
||||
</div>
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="i_fadd">'<tt>fadd</tt>' Instruction</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
|
||||
<pre>
|
||||
<result> = fadd <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
|
||||
<p>The '<tt>fadd</tt>' instruction returns the sum of its two operands.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
|
||||
<p>The two arguments to the '<tt>fadd</tt>' instruction must be
|
||||
<a href="#t_floating">floating point</a> or <a href="#t_vector">vector</a> of
|
||||
floating point values. Both arguments must have identical types.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
|
||||
<p>The value produced is the floating point sum of the two operands.</p>
|
||||
|
||||
<h5>Example:</h5>
|
||||
|
||||
<pre>
|
||||
<result> = fadd float 4.0, %var <i>; yields {float}:result = 4.0 + %var</i>
|
||||
</pre>
|
||||
</div>
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="i_sub">'<tt>sub</tt>' Instruction</a>
|
||||
</div>
|
||||
@ -2550,16 +2585,14 @@ representations.</p>
|
||||
<h5>Arguments:</h5>
|
||||
|
||||
<p>The two arguments to the '<tt>sub</tt>' instruction must be <a
|
||||
href="#t_integer">integer</a>, <a href="#t_floating">floating point</a>,
|
||||
or <a href="#t_vector">vector</a> values. Both arguments must have identical
|
||||
types.</p>
|
||||
href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of
|
||||
integer values. Both arguments must have identical types.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
|
||||
<p>The value produced is the integer or floating point difference of
|
||||
the two operands.</p>
|
||||
<p>The value produced is the integer difference of the two operands.</p>
|
||||
|
||||
<p>If an integer difference has unsigned overflow, the result returned is the
|
||||
<p>If the difference has unsigned overflow, the result returned is the
|
||||
mathematical result modulo 2<sup>n</sup>, where n is the bit width of
|
||||
the result.</p>
|
||||
|
||||
@ -2573,6 +2606,45 @@ instruction is appropriate for both signed and unsigned integers.</p>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="i_fsub">'<tt>fsub</tt>' Instruction</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
|
||||
<pre>
|
||||
<result> = fsub <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
</pre>
|
||||
|
||||
<h5>Overview:</h5>
|
||||
|
||||
<p>The '<tt>fsub</tt>' instruction returns the difference of its two
|
||||
operands.</p>
|
||||
|
||||
<p>Note that the '<tt>fsub</tt>' instruction is used to represent the
|
||||
'<tt>fneg</tt>' instruction present in most other intermediate
|
||||
representations.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
|
||||
<p>The two arguments to the '<tt>fsub</tt>' instruction must be <a
|
||||
<a href="#t_floating">floating point</a> or <a href="#t_vector">vector</a>
|
||||
of floating point values. Both arguments must have identical types.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
|
||||
<p>The value produced is the floating point difference of the two operands.</p>
|
||||
|
||||
<h5>Example:</h5>
|
||||
<pre>
|
||||
<result> = fsub float 4.0, %var <i>; yields {float}:result = 4.0 - %var</i>
|
||||
<result> = fsub float -0.0, %val <i>; yields {float}:result = -%var</i>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="i_mul">'<tt>mul</tt>' Instruction</a>
|
||||
@ -2590,16 +2662,14 @@ operands.</p>
|
||||
<h5>Arguments:</h5>
|
||||
|
||||
<p>The two arguments to the '<tt>mul</tt>' instruction must be <a
|
||||
href="#t_integer">integer</a>, <a href="#t_floating">floating point</a>,
|
||||
or <a href="#t_vector">vector</a> values. Both arguments must have identical
|
||||
types.</p>
|
||||
href="#t_integer">integer</a> or <a href="#t_vector">vector</a> of integer
|
||||
values. Both arguments must have identical types.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
|
||||
<p>The value produced is the integer or floating point product of the
|
||||
two operands.</p>
|
||||
<p>The value produced is the integer product of the two operands.</p>
|
||||
|
||||
<p>If the result of an integer multiplication has unsigned overflow,
|
||||
<p>If the result of the multiplication has unsigned overflow,
|
||||
the result returned is the mathematical result modulo
|
||||
2<sup>n</sup>, where n is the bit width of the result.</p>
|
||||
<p>Because LLVM integers use a two's complement representation, and the
|
||||
@ -2613,6 +2683,35 @@ width of the full product.</p>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection">
|
||||
<a name="i_fmul">'<tt>fmul</tt>' Instruction</a>
|
||||
</div>
|
||||
|
||||
<div class="doc_text">
|
||||
|
||||
<h5>Syntax:</h5>
|
||||
<pre> <result> = fmul <ty> <op1>, <op2> <i>; yields {ty}:result</i>
|
||||
</pre>
|
||||
<h5>Overview:</h5>
|
||||
<p>The '<tt>fmul</tt>' instruction returns the product of its two
|
||||
operands.</p>
|
||||
|
||||
<h5>Arguments:</h5>
|
||||
|
||||
<p>The two arguments to the '<tt>fmul</tt>' instruction must be
|
||||
<a href="#t_floating">floating point</a> or <a href="#t_vector">vector</a>
|
||||
of floating point values. Both arguments must have identical types.</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
|
||||
<p>The value produced is the floating point product of the two operands.</p>
|
||||
|
||||
<h5>Example:</h5>
|
||||
<pre> <result> = fmul float 4.0, %var <i>; yields {float}:result = 4.0 * %var</i>
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<!-- _______________________________________________________________________ -->
|
||||
<div class="doc_subsubsection"> <a name="i_udiv">'<tt>udiv</tt>' Instruction
|
||||
</a></div>
|
||||
@ -7110,7 +7209,7 @@ declare void @llvm.stackprotector( i8* <guard>, i8** <slot> )
|
||||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
Last modified: $Date: 2009-06-03 12:20:10 +0200 (Wed, 03 Jun 2009) $
|
||||
Last modified: $Date: 2009-06-05 00:49:04 +0200 (Fri, 05 Jun 2009) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define LTO_API_VERSION 3
|
||||
|
||||
typedef enum {
|
||||
LTO_SYMBOL_ALIGNMENT_MASK = 0x0000001F, /* log2 of alignment */
|
||||
LTO_SYMBOL_PERMISSIONS_MASK = 0x000000E0,
|
||||
@ -207,6 +209,14 @@ extern void
|
||||
lto_codegen_set_gcc_path(lto_code_gen_t cg, const char* path);
|
||||
|
||||
|
||||
/**
|
||||
* Sets the location of the assembler tool to run. If not set, libLTO
|
||||
* will use gcc to invoke the assembler.
|
||||
*/
|
||||
extern void
|
||||
lto_codegen_set_assembler_path(lto_code_gen_t cg, const char* path);
|
||||
|
||||
|
||||
/**
|
||||
* Adds to a list of all global symbols that must exist in the final
|
||||
* generated code. If a function is not listed, it might be
|
||||
|
@ -270,12 +270,17 @@ protected:
|
||||
NewBBIDom = PredBlocks[i];
|
||||
break;
|
||||
}
|
||||
assert(i != PredBlocks.size() && "No reachable preds?");
|
||||
|
||||
// It's possible that none of the predecessors of NewBB are reachable;
|
||||
// in that case, NewBB itself is unreachable, so nothing needs to be
|
||||
// changed.
|
||||
if (!NewBBIDom)
|
||||
return;
|
||||
|
||||
for (i = i + 1; i < PredBlocks.size(); ++i) {
|
||||
if (DT.isReachableFromEntry(PredBlocks[i]))
|
||||
NewBBIDom = DT.findNearestCommonDominator(NewBBIDom, PredBlocks[i]);
|
||||
}
|
||||
assert(NewBBIDom && "No immediate dominator found??");
|
||||
|
||||
// Create the new dominator tree node... and set the idom of NewBB.
|
||||
DomTreeNodeBase<NodeT> *NewBBNode = DT.addNewBlock(NewBB, NewBBIDom);
|
||||
|
@ -60,12 +60,7 @@ namespace llvm {
|
||||
/// canonical induction variable of the specified type for the specified
|
||||
/// loop (inserting one if there is none). A canonical induction variable
|
||||
/// starts at zero and steps by one on each iteration.
|
||||
Value *getOrInsertCanonicalInductionVariable(const Loop *L, const Type *Ty){
|
||||
assert(Ty->isInteger() && "Can only insert integer induction variables!");
|
||||
SCEVHandle H = SE.getAddRecExpr(SE.getIntegerSCEV(0, Ty),
|
||||
SE.getIntegerSCEV(1, Ty), L);
|
||||
return expand(H);
|
||||
}
|
||||
Value *getOrInsertCanonicalInductionVariable(const Loop *L, const Type *Ty);
|
||||
|
||||
/// addInsertedValue - Remember the specified instruction as being the
|
||||
/// canonical form for the specified SCEV.
|
||||
|
@ -54,13 +54,17 @@ const Attributes Alignment = 31<<16; ///< Alignment of parameter (5 bits)
|
||||
// stored as log2 of alignment with +1 bias
|
||||
// 0 means unaligned different from align 1
|
||||
const Attributes NoCapture = 1<<21; ///< Function creates no aliases of pointer
|
||||
const Attributes NoRedZone = 1<<22; /// disable redzone
|
||||
const Attributes NoImplicitFloat = 1<<23; /// disable implicit floating point
|
||||
/// instructions.
|
||||
|
||||
/// @brief Attributes that only apply to function parameters.
|
||||
const Attributes ParameterOnly = ByVal | Nest | StructRet | NoCapture;
|
||||
|
||||
/// @brief Attributes that only apply to function.
|
||||
const Attributes FunctionOnly = NoReturn | NoUnwind | ReadNone | ReadOnly |
|
||||
NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq;
|
||||
NoInline | AlwaysInline | OptimizeForSize | StackProtect | StackProtectReq |
|
||||
NoRedZone | NoImplicitFloat;
|
||||
|
||||
/// @brief Parameter attributes that do not apply to vararg call arguments.
|
||||
const Attributes VarArgsIncompatible = StructRet;
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
/// emitByte - This callback is invoked when a byte needs to be written to the
|
||||
/// output stream.
|
||||
///
|
||||
void emitByte(unsigned char B) {
|
||||
void emitByte(uint8_t B) {
|
||||
if (CurBufferPtr != BufferEnd)
|
||||
*CurBufferPtr++ = B;
|
||||
}
|
||||
@ -99,10 +99,10 @@ public:
|
||||
///
|
||||
void emitWordLE(unsigned W) {
|
||||
if (4 <= BufferEnd-CurBufferPtr) {
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 0);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 8);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 16);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 24);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 0);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 8);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 16);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 24);
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -113,10 +113,10 @@ public:
|
||||
///
|
||||
void emitWordBE(unsigned W) {
|
||||
if (4 <= BufferEnd-CurBufferPtr) {
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 24);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 16);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 8);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 0);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 24);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 16);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 8);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 0);
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -127,14 +127,14 @@ public:
|
||||
///
|
||||
void emitDWordLE(uint64_t W) {
|
||||
if (8 <= BufferEnd-CurBufferPtr) {
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 0);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 8);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 16);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 24);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 32);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 40);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 48);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 56);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 0);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 8);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 16);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 24);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 32);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 40);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 48);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 56);
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -145,14 +145,14 @@ public:
|
||||
///
|
||||
void emitDWordBE(uint64_t W) {
|
||||
if (8 <= BufferEnd-CurBufferPtr) {
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 56);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 48);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 40);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 32);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 24);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 16);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 8);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 0);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 56);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 48);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 40);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 32);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 24);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 16);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 8);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 0);
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -166,8 +166,8 @@ public:
|
||||
if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) {
|
||||
// Move the current buffer ptr up to the specified alignment.
|
||||
CurBufferPtr =
|
||||
(unsigned char*)(((uintptr_t)CurBufferPtr+Alignment-1) &
|
||||
~(uintptr_t)(Alignment-1));
|
||||
(uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) &
|
||||
~(uintptr_t)(Alignment-1));
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -178,7 +178,7 @@ public:
|
||||
/// written to the output stream.
|
||||
void emitULEB128Bytes(unsigned Value) {
|
||||
do {
|
||||
unsigned char Byte = Value & 0x7f;
|
||||
uint8_t Byte = Value & 0x7f;
|
||||
Value >>= 7;
|
||||
if (Value) Byte |= 0x80;
|
||||
emitByte(Byte);
|
||||
@ -187,12 +187,12 @@ public:
|
||||
|
||||
/// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be
|
||||
/// written to the output stream.
|
||||
void emitSLEB128Bytes(int Value) {
|
||||
int Sign = Value >> (8 * sizeof(Value) - 1);
|
||||
void emitSLEB128Bytes(int32_t Value) {
|
||||
int32_t Sign = Value >> (8 * sizeof(Value) - 1);
|
||||
bool IsMore;
|
||||
|
||||
do {
|
||||
unsigned char Byte = Value & 0x7f;
|
||||
uint8_t Byte = Value & 0x7f;
|
||||
Value >>= 7;
|
||||
IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
|
||||
if (IsMore) Byte |= 0x80;
|
||||
@ -205,14 +205,14 @@ public:
|
||||
void emitString(const std::string &String) {
|
||||
for (unsigned i = 0, N = static_cast<unsigned>(String.size());
|
||||
i < N; ++i) {
|
||||
unsigned char C = String[i];
|
||||
uint8_t C = String[i];
|
||||
emitByte(C);
|
||||
}
|
||||
emitByte(0);
|
||||
}
|
||||
|
||||
/// emitInt32 - Emit a int32 directive.
|
||||
void emitInt32(int Value) {
|
||||
void emitInt32(int32_t Value) {
|
||||
if (4 <= BufferEnd-CurBufferPtr) {
|
||||
*((uint32_t*)CurBufferPtr) = Value;
|
||||
CurBufferPtr += 4;
|
||||
|
@ -50,14 +50,14 @@ class MachineCodeEmitter {
|
||||
protected:
|
||||
/// BufferBegin/BufferEnd - Pointers to the start and end of the memory
|
||||
/// allocated for this code buffer.
|
||||
unsigned char *BufferBegin, *BufferEnd;
|
||||
uint8_t *BufferBegin, *BufferEnd;
|
||||
|
||||
/// CurBufferPtr - Pointer to the next byte of memory to fill when emitting
|
||||
/// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If
|
||||
/// this pointer is at BufferEnd, it will never move due to code emission, and
|
||||
/// all code emission requests will be ignored (this is the buffer overflow
|
||||
/// condition).
|
||||
unsigned char *CurBufferPtr;
|
||||
uint8_t *CurBufferPtr;
|
||||
|
||||
public:
|
||||
virtual ~MachineCodeEmitter() {}
|
||||
@ -96,7 +96,7 @@ public:
|
||||
/// emitByte - This callback is invoked when a byte needs to be written to the
|
||||
/// output stream.
|
||||
///
|
||||
void emitByte(unsigned char B) {
|
||||
void emitByte(uint8_t B) {
|
||||
if (CurBufferPtr != BufferEnd)
|
||||
*CurBufferPtr++ = B;
|
||||
}
|
||||
@ -106,10 +106,10 @@ public:
|
||||
///
|
||||
void emitWordLE(unsigned W) {
|
||||
if (4 <= BufferEnd-CurBufferPtr) {
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 0);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 8);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 16);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 24);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 0);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 8);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 16);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 24);
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -120,10 +120,10 @@ public:
|
||||
///
|
||||
void emitWordBE(unsigned W) {
|
||||
if (4 <= BufferEnd-CurBufferPtr) {
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 24);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 16);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 8);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 0);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 24);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 16);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 8);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 0);
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -134,14 +134,14 @@ public:
|
||||
///
|
||||
void emitDWordLE(uint64_t W) {
|
||||
if (8 <= BufferEnd-CurBufferPtr) {
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 0);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 8);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 16);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 24);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 32);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 40);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 48);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 56);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 0);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 8);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 16);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 24);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 32);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 40);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 48);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 56);
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -152,14 +152,14 @@ public:
|
||||
///
|
||||
void emitDWordBE(uint64_t W) {
|
||||
if (8 <= BufferEnd-CurBufferPtr) {
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 56);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 48);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 40);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 32);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 24);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 16);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 8);
|
||||
*CurBufferPtr++ = (unsigned char)(W >> 0);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 56);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 48);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 40);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 32);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 24);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 16);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 8);
|
||||
*CurBufferPtr++ = (uint8_t)(W >> 0);
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -173,8 +173,8 @@ public:
|
||||
if(Alignment <= (uintptr_t)(BufferEnd-CurBufferPtr)) {
|
||||
// Move the current buffer ptr up to the specified alignment.
|
||||
CurBufferPtr =
|
||||
(unsigned char*)(((uintptr_t)CurBufferPtr+Alignment-1) &
|
||||
~(uintptr_t)(Alignment-1));
|
||||
(uint8_t*)(((uintptr_t)CurBufferPtr+Alignment-1) &
|
||||
~(uintptr_t)(Alignment-1));
|
||||
} else {
|
||||
CurBufferPtr = BufferEnd;
|
||||
}
|
||||
@ -185,7 +185,7 @@ public:
|
||||
/// written to the output stream.
|
||||
void emitULEB128Bytes(unsigned Value) {
|
||||
do {
|
||||
unsigned char Byte = Value & 0x7f;
|
||||
uint8_t Byte = Value & 0x7f;
|
||||
Value >>= 7;
|
||||
if (Value) Byte |= 0x80;
|
||||
emitByte(Byte);
|
||||
@ -194,12 +194,12 @@ public:
|
||||
|
||||
/// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be
|
||||
/// written to the output stream.
|
||||
void emitSLEB128Bytes(int Value) {
|
||||
int Sign = Value >> (8 * sizeof(Value) - 1);
|
||||
void emitSLEB128Bytes(int32_t Value) {
|
||||
int32_t Sign = Value >> (8 * sizeof(Value) - 1);
|
||||
bool IsMore;
|
||||
|
||||
do {
|
||||
unsigned char Byte = Value & 0x7f;
|
||||
uint8_t Byte = Value & 0x7f;
|
||||
Value >>= 7;
|
||||
IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
|
||||
if (IsMore) Byte |= 0x80;
|
||||
@ -212,14 +212,14 @@ public:
|
||||
void emitString(const std::string &String) {
|
||||
for (unsigned i = 0, N = static_cast<unsigned>(String.size());
|
||||
i < N; ++i) {
|
||||
unsigned char C = String[i];
|
||||
uint8_t C = String[i];
|
||||
emitByte(C);
|
||||
}
|
||||
emitByte(0);
|
||||
}
|
||||
|
||||
/// emitInt32 - Emit a int32 directive.
|
||||
void emitInt32(int Value) {
|
||||
void emitInt32(int32_t Value) {
|
||||
if (4 <= BufferEnd-CurBufferPtr) {
|
||||
*((uint32_t*)CurBufferPtr) = Value;
|
||||
CurBufferPtr += 4;
|
||||
|
@ -18,17 +18,17 @@
|
||||
#undef ENABLE_CBE_PRINTF_A
|
||||
|
||||
/* Define if position independent code is enabled */
|
||||
#undef ENABLE_PIC
|
||||
#cmakedefine ENABLE_PIC ${ENABLE_PIC}
|
||||
|
||||
/* Define if threads enabled */
|
||||
#cmakedefine ENABLE_THREADS ${ENABLE_THREADS}
|
||||
|
||||
/* Define to 1 if you have `alloca', as a function or macro. */
|
||||
#undef HAVE_ALLOCA
|
||||
#cmakedefine HAVE_ALLOCA ${HAVE_ALLOCA}
|
||||
|
||||
/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
|
||||
*/
|
||||
#undef HAVE_ALLOCA_H
|
||||
#cmakedefine HAVE_ALLOCA_H ${HAVE_ALLOCA_H}
|
||||
|
||||
/* Define to 1 if you have the `argz_append' function. */
|
||||
#undef HAVE_ARGZ_APPEND
|
||||
@ -228,7 +228,7 @@
|
||||
#cmakedefine HAVE_MALLOC_MALLOC_H ${HAVE_MALLOC_MALLOC_H}
|
||||
|
||||
/* Define to 1 if you have the `malloc_zone_statistics' function. */
|
||||
#undef HAVE_MALLOC_ZONE_STATISTICS
|
||||
#cmakedefine HAVE_MALLOC_ZONE_STATISTICS ${HAVE_MALLOC_ZONE_STATISTICS}
|
||||
|
||||
/* Define to 1 if you have the `memcpy' function. */
|
||||
#undef HAVE_MEMCPY
|
||||
@ -414,7 +414,7 @@
|
||||
#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H}
|
||||
|
||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
#cmakedefine HAVE_SYS_WAIT_H ${HAVE_SYS_WAIT_H}
|
||||
|
||||
/* Define to 1 if the system has the type `uint64_t'. */
|
||||
#undef HAVE_UINT64_T
|
||||
|
@ -704,10 +704,14 @@ public:
|
||||
/// specify the full Instruction::OPCODE identifier.
|
||||
///
|
||||
static Constant *getNeg(Constant *C);
|
||||
static Constant *getFNeg(Constant *C);
|
||||
static Constant *getNot(Constant *C);
|
||||
static Constant *getAdd(Constant *C1, Constant *C2);
|
||||
static Constant *getFAdd(Constant *C1, Constant *C2);
|
||||
static Constant *getSub(Constant *C1, Constant *C2);
|
||||
static Constant *getFSub(Constant *C1, Constant *C2);
|
||||
static Constant *getMul(Constant *C1, Constant *C2);
|
||||
static Constant *getFMul(Constant *C1, Constant *C2);
|
||||
static Constant *getUDiv(Constant *C1, Constant *C2);
|
||||
static Constant *getSDiv(Constant *C1, Constant *C2);
|
||||
static Constant *getFDiv(Constant *C1, Constant *C2);
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
|
||||
/// getGOTBase - If this is managing a Global Offset Table, this method should
|
||||
/// return a pointer to its base.
|
||||
virtual unsigned char *getGOTBase() const = 0;
|
||||
virtual uint8_t *getGOTBase() const = 0;
|
||||
|
||||
/// SetDlsymTable - If the JIT must be able to relocate stubs after they have
|
||||
/// been emitted, potentially because they are being copied to a process
|
||||
@ -89,8 +89,8 @@ public:
|
||||
/// emit the function, so it doesn't pass in the size. Instead, this method
|
||||
/// is required to pass back a "valid size". The JIT will be careful to not
|
||||
/// write more than the returned ActualSize bytes of memory.
|
||||
virtual unsigned char *startFunctionBody(const Function *F,
|
||||
uintptr_t &ActualSize) = 0;
|
||||
virtual uint8_t *startFunctionBody(const Function *F,
|
||||
uintptr_t &ActualSize) = 0;
|
||||
|
||||
/// allocateStub - This method is called by the JIT to allocate space for a
|
||||
/// function stub (used to handle limited branch displacements) while it is
|
||||
@ -100,9 +100,8 @@ public:
|
||||
/// thunk for it. The stub should be "close" to the current function body,
|
||||
/// but should not be included in the 'actualsize' returned by
|
||||
/// startFunctionBody.
|
||||
virtual unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
|
||||
unsigned Alignment) =0;
|
||||
|
||||
virtual uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
|
||||
unsigned Alignment) = 0;
|
||||
|
||||
/// endFunctionBody - This method is called when the JIT is done codegen'ing
|
||||
/// the specified function. At this point we know the size of the JIT
|
||||
@ -110,11 +109,11 @@ public:
|
||||
/// the startFunctionBody method) and FunctionEnd which is a pointer to the
|
||||
/// actual end of the function. This method should mark the space allocated
|
||||
/// and remember where it is in case the client wants to deallocate it.
|
||||
virtual void endFunctionBody(const Function *F, unsigned char *FunctionStart,
|
||||
unsigned char *FunctionEnd) = 0;
|
||||
virtual void endFunctionBody(const Function *F, uint8_t *FunctionStart,
|
||||
uint8_t *FunctionEnd) = 0;
|
||||
|
||||
/// allocateSpace - Allocate a memory block of the given size.
|
||||
virtual unsigned char *allocateSpace(intptr_t Size, unsigned Alignment) = 0;
|
||||
virtual uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) = 0;
|
||||
|
||||
/// deallocateMemForFunction - Free JIT memory for the specified function.
|
||||
/// This is never called when the JIT is currently emitting a function.
|
||||
@ -122,14 +121,13 @@ public:
|
||||
|
||||
/// startExceptionTable - When we finished JITing the function, if exception
|
||||
/// handling is set, we emit the exception table.
|
||||
virtual unsigned char* startExceptionTable(const Function* F,
|
||||
uintptr_t &ActualSize) = 0;
|
||||
virtual uint8_t* startExceptionTable(const Function* F,
|
||||
uintptr_t &ActualSize) = 0;
|
||||
|
||||
/// endExceptionTable - This method is called when the JIT is done emitting
|
||||
/// the exception table.
|
||||
virtual void endExceptionTable(const Function *F, unsigned char *TableStart,
|
||||
unsigned char *TableEnd,
|
||||
unsigned char* FrameRegister) = 0;
|
||||
virtual void endExceptionTable(const Function *F, uint8_t *TableStart,
|
||||
uint8_t *TableEnd, uint8_t* FrameRegister) = 0;
|
||||
};
|
||||
|
||||
} // end namespace llvm.
|
||||
|
@ -204,21 +204,30 @@ public:
|
||||
Instruction *InsertBefore = 0);
|
||||
static BinaryOperator *CreateNeg(Value *Op, const std::string &Name,
|
||||
BasicBlock *InsertAtEnd);
|
||||
static BinaryOperator *CreateFNeg(Value *Op, const std::string &Name = "",
|
||||
Instruction *InsertBefore = 0);
|
||||
static BinaryOperator *CreateFNeg(Value *Op, const std::string &Name,
|
||||
BasicBlock *InsertAtEnd);
|
||||
static BinaryOperator *CreateNot(Value *Op, const std::string &Name = "",
|
||||
Instruction *InsertBefore = 0);
|
||||
static BinaryOperator *CreateNot(Value *Op, const std::string &Name,
|
||||
BasicBlock *InsertAtEnd);
|
||||
|
||||
/// isNeg, isNot - Check if the given Value is a NEG or NOT instruction.
|
||||
/// isNeg, isFNeg, isNot - Check if the given Value is a
|
||||
/// NEG, FNeg, or NOT instruction.
|
||||
///
|
||||
static bool isNeg(const Value *V);
|
||||
static bool isFNeg(const Value *V);
|
||||
static bool isNot(const Value *V);
|
||||
|
||||
/// getNegArgument, getNotArgument - Helper functions to extract the
|
||||
/// unary argument of a NEG or NOT operation implemented via Sub or Xor.
|
||||
/// unary argument of a NEG, FNEG or NOT operation implemented via
|
||||
/// Sub, FSub, or Xor.
|
||||
///
|
||||
static const Value *getNegArgument(const Value *BinOp);
|
||||
static Value *getNegArgument( Value *BinOp);
|
||||
static const Value *getFNegArgument(const Value *BinOp);
|
||||
static Value *getFNegArgument( Value *BinOp);
|
||||
static const Value *getNotArgument(const Value *BinOp);
|
||||
static Value *getNotArgument( Value *BinOp);
|
||||
|
||||
|
@ -105,71 +105,74 @@ HANDLE_TERM_INST ( 6, Unreachable, UnreachableInst)
|
||||
// Standard binary operators...
|
||||
FIRST_BINARY_INST( 7)
|
||||
HANDLE_BINARY_INST( 7, Add , BinaryOperator)
|
||||
HANDLE_BINARY_INST( 8, Sub , BinaryOperator)
|
||||
HANDLE_BINARY_INST( 9, Mul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(10, UDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(11, SDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(12, FDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(13, URem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(14, SRem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(15, FRem , BinaryOperator)
|
||||
HANDLE_BINARY_INST( 8, FAdd , BinaryOperator)
|
||||
HANDLE_BINARY_INST( 9, Sub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(10, FSub , BinaryOperator)
|
||||
HANDLE_BINARY_INST(11, Mul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(12, FMul , BinaryOperator)
|
||||
HANDLE_BINARY_INST(13, UDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(14, SDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(15, FDiv , BinaryOperator)
|
||||
HANDLE_BINARY_INST(16, URem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(17, SRem , BinaryOperator)
|
||||
HANDLE_BINARY_INST(18, FRem , BinaryOperator)
|
||||
|
||||
// Logical operators (integer operands)
|
||||
HANDLE_BINARY_INST(16, Shl , BinaryOperator) // Shift left (logical)
|
||||
HANDLE_BINARY_INST(17, LShr , BinaryOperator) // Shift right (logical)
|
||||
HANDLE_BINARY_INST(18, AShr , BinaryOperator) // Shift right (arithmetic)
|
||||
HANDLE_BINARY_INST(19, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(20, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(21, Xor , BinaryOperator)
|
||||
LAST_BINARY_INST(21)
|
||||
HANDLE_BINARY_INST(19, Shl , BinaryOperator) // Shift left (logical)
|
||||
HANDLE_BINARY_INST(20, LShr , BinaryOperator) // Shift right (logical)
|
||||
HANDLE_BINARY_INST(21, AShr , BinaryOperator) // Shift right (arithmetic)
|
||||
HANDLE_BINARY_INST(22, And , BinaryOperator)
|
||||
HANDLE_BINARY_INST(23, Or , BinaryOperator)
|
||||
HANDLE_BINARY_INST(24, Xor , BinaryOperator)
|
||||
LAST_BINARY_INST(24)
|
||||
|
||||
// Memory operators...
|
||||
FIRST_MEMORY_INST(22)
|
||||
HANDLE_MEMORY_INST(22, Malloc, MallocInst) // Heap management instructions
|
||||
HANDLE_MEMORY_INST(23, Free , FreeInst )
|
||||
HANDLE_MEMORY_INST(24, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(25, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(26, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(27, GetElementPtr, GetElementPtrInst)
|
||||
LAST_MEMORY_INST(27)
|
||||
FIRST_MEMORY_INST(25)
|
||||
HANDLE_MEMORY_INST(25, Malloc, MallocInst) // Heap management instructions
|
||||
HANDLE_MEMORY_INST(26, Free , FreeInst )
|
||||
HANDLE_MEMORY_INST(27, Alloca, AllocaInst) // Stack management
|
||||
HANDLE_MEMORY_INST(28, Load , LoadInst ) // Memory manipulation instrs
|
||||
HANDLE_MEMORY_INST(29, Store , StoreInst )
|
||||
HANDLE_MEMORY_INST(30, GetElementPtr, GetElementPtrInst)
|
||||
LAST_MEMORY_INST(30)
|
||||
|
||||
// Cast operators ...
|
||||
// NOTE: The order matters here because CastInst::isEliminableCastPair
|
||||
// NOTE: (see Instructions.cpp) encodes a table based on this ordering.
|
||||
FIRST_CAST_INST(28)
|
||||
HANDLE_CAST_INST(28, Trunc , TruncInst ) // Truncate integers
|
||||
HANDLE_CAST_INST(29, ZExt , ZExtInst ) // Zero extend integers
|
||||
HANDLE_CAST_INST(30, SExt , SExtInst ) // Sign extend integers
|
||||
HANDLE_CAST_INST(31, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||
HANDLE_CAST_INST(32, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||
HANDLE_CAST_INST(33, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||
HANDLE_CAST_INST(34, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||
HANDLE_CAST_INST(35, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||
HANDLE_CAST_INST(36, FPExt , FPExtInst ) // Extend floating point
|
||||
HANDLE_CAST_INST(37, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||
HANDLE_CAST_INST(38, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||
HANDLE_CAST_INST(39, BitCast , BitCastInst ) // Type cast
|
||||
LAST_CAST_INST(39)
|
||||
FIRST_CAST_INST(31)
|
||||
HANDLE_CAST_INST(31, Trunc , TruncInst ) // Truncate integers
|
||||
HANDLE_CAST_INST(32, ZExt , ZExtInst ) // Zero extend integers
|
||||
HANDLE_CAST_INST(33, SExt , SExtInst ) // Sign extend integers
|
||||
HANDLE_CAST_INST(34, FPToUI , FPToUIInst ) // floating point -> UInt
|
||||
HANDLE_CAST_INST(35, FPToSI , FPToSIInst ) // floating point -> SInt
|
||||
HANDLE_CAST_INST(36, UIToFP , UIToFPInst ) // UInt -> floating point
|
||||
HANDLE_CAST_INST(37, SIToFP , SIToFPInst ) // SInt -> floating point
|
||||
HANDLE_CAST_INST(38, FPTrunc , FPTruncInst ) // Truncate floating point
|
||||
HANDLE_CAST_INST(39, FPExt , FPExtInst ) // Extend floating point
|
||||
HANDLE_CAST_INST(40, PtrToInt, PtrToIntInst) // Pointer -> Integer
|
||||
HANDLE_CAST_INST(41, IntToPtr, IntToPtrInst) // Integer -> Pointer
|
||||
HANDLE_CAST_INST(42, BitCast , BitCastInst ) // Type cast
|
||||
LAST_CAST_INST(42)
|
||||
|
||||
// Other operators...
|
||||
FIRST_OTHER_INST(40)
|
||||
HANDLE_OTHER_INST(40, ICmp , ICmpInst ) // Integer comparison instruction
|
||||
HANDLE_OTHER_INST(41, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||
HANDLE_OTHER_INST(42, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(43, Call , CallInst ) // Call a function
|
||||
HANDLE_OTHER_INST(44, Select , SelectInst ) // select instruction
|
||||
HANDLE_OTHER_INST(45, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(46, UserOp2, Instruction) // Internal to passes only
|
||||
HANDLE_OTHER_INST(47, VAArg , VAArgInst ) // vaarg instruction
|
||||
HANDLE_OTHER_INST(48, ExtractElement, ExtractElementInst)// extract from vector
|
||||
HANDLE_OTHER_INST(49, InsertElement, InsertElementInst) // insert into vector
|
||||
HANDLE_OTHER_INST(50, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||
HANDLE_OTHER_INST(51, ExtractValue, ExtractValueInst)// extract from aggregate
|
||||
HANDLE_OTHER_INST(52, InsertValue, InsertValueInst) // insert into aggregate
|
||||
HANDLE_OTHER_INST(53, VICmp , VICmpInst ) // Vec Int comparison instruction.
|
||||
HANDLE_OTHER_INST(54, VFCmp , VFCmpInst ) // Vec FP point comparison instr.
|
||||
FIRST_OTHER_INST(43)
|
||||
HANDLE_OTHER_INST(43, ICmp , ICmpInst ) // Integer comparison instruction
|
||||
HANDLE_OTHER_INST(44, FCmp , FCmpInst ) // Floating point comparison instr.
|
||||
HANDLE_OTHER_INST(45, PHI , PHINode ) // PHI node instruction
|
||||
HANDLE_OTHER_INST(46, Call , CallInst ) // Call a function
|
||||
HANDLE_OTHER_INST(47, Select , SelectInst ) // select instruction
|
||||
HANDLE_OTHER_INST(48, UserOp1, Instruction) // May be used internally in a pass
|
||||
HANDLE_OTHER_INST(49, UserOp2, Instruction) // Internal to passes only
|
||||
HANDLE_OTHER_INST(50, VAArg , VAArgInst ) // vaarg instruction
|
||||
HANDLE_OTHER_INST(51, ExtractElement, ExtractElementInst)// extract from vector
|
||||
HANDLE_OTHER_INST(52, InsertElement, InsertElementInst) // insert into vector
|
||||
HANDLE_OTHER_INST(53, ShuffleVector, ShuffleVectorInst) // shuffle two vectors.
|
||||
HANDLE_OTHER_INST(54, ExtractValue, ExtractValueInst)// extract from aggregate
|
||||
HANDLE_OTHER_INST(55, InsertValue, InsertValueInst) // insert into aggregate
|
||||
HANDLE_OTHER_INST(56, VICmp , VICmpInst ) // Vec Int comparison instruction.
|
||||
HANDLE_OTHER_INST(57, VFCmp , VFCmpInst ) // Vec FP point comparison instr.
|
||||
|
||||
LAST_OTHER_INST(55)
|
||||
LAST_OTHER_INST(57)
|
||||
|
||||
#undef FIRST_TERM_INST
|
||||
#undef HANDLE_TERM_INST
|
||||
|
@ -32,12 +32,21 @@ public:
|
||||
Constant *CreateAdd(Constant *LHS, Constant *RHS) const {
|
||||
return ConstantExpr::getAdd(LHS, RHS);
|
||||
}
|
||||
Constant *CreateFAdd(Constant *LHS, Constant *RHS) const {
|
||||
return ConstantExpr::getFAdd(LHS, RHS);
|
||||
}
|
||||
Constant *CreateSub(Constant *LHS, Constant *RHS) const {
|
||||
return ConstantExpr::getSub(LHS, RHS);
|
||||
}
|
||||
Constant *CreateFSub(Constant *LHS, Constant *RHS) const {
|
||||
return ConstantExpr::getFSub(LHS, RHS);
|
||||
}
|
||||
Constant *CreateMul(Constant *LHS, Constant *RHS) const {
|
||||
return ConstantExpr::getMul(LHS, RHS);
|
||||
}
|
||||
Constant *CreateFMul(Constant *LHS, Constant *RHS) const {
|
||||
return ConstantExpr::getFMul(LHS, RHS);
|
||||
}
|
||||
Constant *CreateUDiv(Constant *LHS, Constant *RHS) const {
|
||||
return ConstantExpr::getUDiv(LHS, RHS);
|
||||
}
|
||||
@ -87,6 +96,9 @@ public:
|
||||
Constant *CreateNeg(Constant *C) const {
|
||||
return ConstantExpr::getNeg(C);
|
||||
}
|
||||
Constant *CreateFNeg(Constant *C) const {
|
||||
return ConstantExpr::getFNeg(C);
|
||||
}
|
||||
Constant *CreateNot(Constant *C) const {
|
||||
return ConstantExpr::getNot(C);
|
||||
}
|
||||
|
@ -175,18 +175,36 @@ public:
|
||||
return Folder.CreateAdd(LC, RC);
|
||||
return Insert(BinaryOperator::CreateAdd(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateFAdd(Value *LHS, Value *RHS, const char *Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Folder.CreateFAdd(LC, RC);
|
||||
return Insert(BinaryOperator::CreateFAdd(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateSub(Value *LHS, Value *RHS, const char *Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Folder.CreateSub(LC, RC);
|
||||
return Insert(BinaryOperator::CreateSub(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateFSub(Value *LHS, Value *RHS, const char *Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Folder.CreateFSub(LC, RC);
|
||||
return Insert(BinaryOperator::CreateFSub(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateMul(Value *LHS, Value *RHS, const char *Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Folder.CreateMul(LC, RC);
|
||||
return Insert(BinaryOperator::CreateMul(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateFMul(Value *LHS, Value *RHS, const char *Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
return Folder.CreateMul(LC, RC);
|
||||
return Insert(BinaryOperator::CreateFMul(LHS, RHS), Name);
|
||||
}
|
||||
Value *CreateUDiv(Value *LHS, Value *RHS, const char *Name = "") {
|
||||
if (Constant *LC = dyn_cast<Constant>(LHS))
|
||||
if (Constant *RC = dyn_cast<Constant>(RHS))
|
||||
|
@ -39,12 +39,21 @@ public:
|
||||
Value *CreateAdd(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateAdd(LHS, RHS);
|
||||
}
|
||||
Value *CreateFAdd(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateFAdd(LHS, RHS);
|
||||
}
|
||||
Value *CreateSub(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateSub(LHS, RHS);
|
||||
}
|
||||
Value *CreateFSub(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateFSub(LHS, RHS);
|
||||
}
|
||||
Value *CreateMul(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateMul(LHS, RHS);
|
||||
}
|
||||
Value *CreateFMul(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateFMul(LHS, RHS);
|
||||
}
|
||||
Value *CreateUDiv(Constant *LHS, Constant *RHS) const {
|
||||
return BinaryOperator::CreateUDiv(LHS, RHS);
|
||||
}
|
||||
|
@ -156,18 +156,36 @@ inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L,
|
||||
return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::FAdd> m_FAdd(const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOp_match<LHS, RHS, Instruction::FAdd>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::FSub> m_FSub(const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOp_match<LHS, RHS, Instruction::FSub>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::FMul> m_FMul(const LHS &L,
|
||||
const RHS &R) {
|
||||
return BinaryOp_match<LHS, RHS, Instruction::FMul>(L, R);
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L,
|
||||
const RHS &R) {
|
||||
@ -494,6 +512,35 @@ template<typename LHS>
|
||||
inline neg_match<LHS> m_Neg(const LHS &L) { return L; }
|
||||
|
||||
|
||||
template<typename LHS_t>
|
||||
struct fneg_match {
|
||||
LHS_t L;
|
||||
|
||||
fneg_match(const LHS_t &LHS) : L(LHS) {}
|
||||
|
||||
template<typename OpTy>
|
||||
bool match(OpTy *V) {
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
if (I->getOpcode() == Instruction::FSub)
|
||||
return matchIfFNeg(I->getOperand(0), I->getOperand(1));
|
||||
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))
|
||||
if (CE->getOpcode() == Instruction::FSub)
|
||||
return matchIfFNeg(CE->getOperand(0), CE->getOperand(1));
|
||||
if (ConstantFP *CF = dyn_cast<ConstantFP>(V))
|
||||
return L.match(ConstantExpr::getFNeg(CF));
|
||||
return false;
|
||||
}
|
||||
private:
|
||||
bool matchIfFNeg(Value *LHS, Value *RHS) {
|
||||
return LHS == ConstantExpr::getZeroValueForNegationExpr(LHS->getType()) &&
|
||||
L.match(RHS);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename LHS>
|
||||
inline fneg_match<LHS> m_FNeg(const LHS &L) { return L; }
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Matchers for control flow
|
||||
//
|
||||
|
@ -60,15 +60,10 @@ namespace llvm {
|
||||
///
|
||||
/// Internalize - Run the internalize pass.
|
||||
/// RunInliner - Use a function inlining pass.
|
||||
/// RunSecondGlobalOpt - Run the global optimizer pass twice.
|
||||
/// VerifyEach - Run the verifier after each pass.
|
||||
//
|
||||
// FIXME: RunSecondGlobalOpt should go away once we resolve which of LTO or
|
||||
// llvm-ld is better.
|
||||
static inline void createStandardLTOPasses(PassManager *PM,
|
||||
bool Internalize,
|
||||
bool RunInliner,
|
||||
bool RunSecondGlobalOpt,
|
||||
bool VerifyEach);
|
||||
|
||||
// Implementations
|
||||
@ -173,7 +168,6 @@ namespace llvm {
|
||||
static inline void createStandardLTOPasses(PassManager *PM,
|
||||
bool Internalize,
|
||||
bool RunInliner,
|
||||
bool RunSecondGlobalOpt,
|
||||
bool VerifyEach) {
|
||||
// Now that composite has been compiled, scan through the module, looking
|
||||
// for a main function. If main is defined, mark all other functions
|
||||
@ -207,8 +201,8 @@ namespace llvm {
|
||||
addOnePass(PM, createFunctionInliningPass(), VerifyEach);
|
||||
|
||||
addOnePass(PM, createPruneEHPass(), VerifyEach); // Remove dead EH info.
|
||||
// Optimize globals again.
|
||||
if (RunSecondGlobalOpt)
|
||||
// Optimize globals again if we ran the inliner.
|
||||
if (RunInliner)
|
||||
addOnePass(PM, createGlobalOptimizerPass(), VerifyEach);
|
||||
addOnePass(PM, createGlobalDCEPass(), VerifyEach); // Remove dead functions.
|
||||
|
||||
|
@ -48,12 +48,21 @@ public:
|
||||
Constant *CreateAdd(Constant *LHS, Constant *RHS) const {
|
||||
return Fold(ConstantExpr::getAdd(LHS, RHS));
|
||||
}
|
||||
Constant *CreateFAdd(Constant *LHS, Constant *RHS) const {
|
||||
return Fold(ConstantExpr::getFAdd(LHS, RHS));
|
||||
}
|
||||
Constant *CreateSub(Constant *LHS, Constant *RHS) const {
|
||||
return Fold(ConstantExpr::getSub(LHS, RHS));
|
||||
}
|
||||
Constant *CreateFSub(Constant *LHS, Constant *RHS) const {
|
||||
return Fold(ConstantExpr::getFSub(LHS, RHS));
|
||||
}
|
||||
Constant *CreateMul(Constant *LHS, Constant *RHS) const {
|
||||
return Fold(ConstantExpr::getMul(LHS, RHS));
|
||||
}
|
||||
Constant *CreateFMul(Constant *LHS, Constant *RHS) const {
|
||||
return Fold(ConstantExpr::getFMul(LHS, RHS));
|
||||
}
|
||||
Constant *CreateUDiv(Constant *LHS, Constant *RHS) const {
|
||||
return Fold(ConstantExpr::getUDiv(LHS, RHS));
|
||||
}
|
||||
@ -103,6 +112,9 @@ public:
|
||||
Constant *CreateNeg(Constant *C) const {
|
||||
return Fold(ConstantExpr::getNeg(C));
|
||||
}
|
||||
Constant *CreateFNeg(Constant *C) const {
|
||||
return Fold(ConstantExpr::getFNeg(C));
|
||||
}
|
||||
Constant *CreateNot(Constant *C) const {
|
||||
return Fold(ConstantExpr::getNot(C));
|
||||
}
|
||||
|
@ -45,6 +45,19 @@ private:
|
||||
bool Unbuffered;
|
||||
|
||||
public:
|
||||
// color order matches ANSI escape sequence, don't change
|
||||
enum Colors {
|
||||
BLACK=0,
|
||||
RED,
|
||||
GREEN,
|
||||
YELLOW,
|
||||
BLUE,
|
||||
MAGENTA,
|
||||
CYAN,
|
||||
WHITE,
|
||||
SAVEDCOLOR
|
||||
};
|
||||
|
||||
explicit raw_ostream(bool unbuffered=false) : Unbuffered(unbuffered) {
|
||||
// Start out ready to flush.
|
||||
OutBufStart = OutBufEnd = OutBufCur = 0;
|
||||
@ -167,6 +180,20 @@ public:
|
||||
// Formatted output, see the format() function in Support/Format.h.
|
||||
raw_ostream &operator<<(const format_object_base &Fmt);
|
||||
|
||||
/// Changes the foreground color of text that will be output from this point
|
||||
/// forward.
|
||||
/// @param colors ANSI color to use, the special SAVEDCOLOR can be used to
|
||||
/// change only the bold attribute, and keep colors untouched
|
||||
/// @param bold bold/brighter text, default false
|
||||
/// @param bg if true change the background, default: change foreground
|
||||
/// @returns itself so it can be used within << invocations
|
||||
virtual raw_ostream &changeColor(enum Colors colors, bool bold=false,
|
||||
bool bg=false) { return *this; }
|
||||
|
||||
/// Resets the colors to terminal defaults. Call this when you are done
|
||||
/// outputting colored text, or before program exit.
|
||||
virtual raw_ostream &resetColor() { return *this; }
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Subclass Interface
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -243,6 +270,10 @@ public:
|
||||
/// seek - Flushes the stream and repositions the underlying file descriptor
|
||||
/// positition to the offset specified from the beginning of the file.
|
||||
uint64_t seek(uint64_t off);
|
||||
|
||||
virtual raw_ostream &changeColor(enum Colors colors, bool bold=false,
|
||||
bool bg=false);
|
||||
virtual raw_ostream &resetColor();
|
||||
};
|
||||
|
||||
/// raw_stdout_ostream - This is a stream that always prints to stdout.
|
||||
|
@ -107,6 +107,34 @@ namespace sys {
|
||||
/// console, or if the number of columns cannot be determined,
|
||||
/// this routine returns zero.
|
||||
static unsigned StandardErrColumns();
|
||||
|
||||
/// This function determines whether the terminal connected to standard
|
||||
/// output supports colors. If standard output is not connected to a
|
||||
/// terminal, this function returns false.
|
||||
static bool StandardOutHasColors();
|
||||
|
||||
/// This function determines whether the terminal connected to standard
|
||||
/// error supports colors. If standard error is not connected to a
|
||||
/// terminal, this function returns false.
|
||||
static bool StandardErrHasColors();
|
||||
|
||||
/// Whether changing colors requires the output to be flushed.
|
||||
/// This is needed on systems that don't support escape sequences for
|
||||
/// changing colors.
|
||||
static bool ColorNeedsFlush();
|
||||
|
||||
/// This function returns the colorcode escape sequences.
|
||||
/// If ColorNeedsFlush() is true then this function will change the colors
|
||||
/// and return an empty escape sequence. In that case it is the
|
||||
/// responsibility of the client to flush the output stream prior to
|
||||
/// calling this function.
|
||||
static const char *OutputColor(char c, bool bold, bool bg);
|
||||
|
||||
/// Same as OutputColor, but only enables the bold attribute.
|
||||
static const char *OutputBold(bool bg);
|
||||
|
||||
/// Resets the terminals colors, or returns an escape sequence to do so.
|
||||
static const char *ResetColor();
|
||||
/// @}
|
||||
};
|
||||
}
|
||||
|
@ -25,9 +25,23 @@ namespace llvm {
|
||||
// e_machine member of the ELF header.
|
||||
unsigned short EMachine;
|
||||
public:
|
||||
|
||||
// Machine architectures
|
||||
enum MachineType {
|
||||
NoMachine,
|
||||
EM_386 = 3
|
||||
EM_NONE = 0, // No machine
|
||||
EM_M32 = 1, // AT&T WE 32100
|
||||
EM_SPARC = 2, // SPARC
|
||||
EM_386 = 3, // Intel 386
|
||||
EM_68K = 4, // Motorola 68000
|
||||
EM_88K = 5, // Motorola 88000
|
||||
EM_486 = 6, // Intel 486 (deprecated)
|
||||
EM_860 = 7, // Intel 80860
|
||||
EM_MIPS = 8, // MIPS R3000
|
||||
EM_PPC = 20, // PowerPC
|
||||
EM_ARM = 40, // ARM
|
||||
EM_ALPHA = 41, // DEC Alpha
|
||||
EM_SPARCV9 = 43, // SPARC V9
|
||||
EM_X86_64 = 62 // AMD64
|
||||
};
|
||||
|
||||
explicit TargetELFWriterInfo(MachineType machine) : EMachine(machine) {}
|
||||
|
@ -632,7 +632,8 @@ public:
|
||||
/// It returns MVT::iAny if SelectionDAG should be responsible for
|
||||
/// determining it.
|
||||
virtual MVT getOptimalMemOpType(uint64_t Size, unsigned Align,
|
||||
bool isSrcConst, bool isSrcStr) const {
|
||||
bool isSrcConst, bool isSrcStr,
|
||||
SelectionDAG &DAG) const {
|
||||
return MVT::iAny;
|
||||
}
|
||||
|
||||
@ -825,11 +826,11 @@ public:
|
||||
virtual bool
|
||||
isGAPlusOffset(SDNode *N, GlobalValue* &GA, int64_t &Offset) const;
|
||||
|
||||
/// isConsecutiveLoad - Return true if LD (which must be a LoadSDNode) is
|
||||
/// loading 'Bytes' bytes from a location that is 'Dist' units away from the
|
||||
/// location that the 'Base' load is loading from.
|
||||
bool isConsecutiveLoad(SDNode *LD, SDNode *Base, unsigned Bytes, int Dist,
|
||||
const MachineFrameInfo *MFI) const;
|
||||
/// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a
|
||||
/// location that is 'Dist' units away from the location that the 'Base' load
|
||||
/// is loading from.
|
||||
bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes,
|
||||
int Dist, const MachineFrameInfo *MFI) const;
|
||||
|
||||
/// PerformDAGCombine - This method will be invoked for all target nodes and
|
||||
/// for any target-independent nodes that the target has registered with
|
||||
|
@ -73,12 +73,6 @@ namespace llvm {
|
||||
/// target FP instructions.
|
||||
extern bool UseSoftFloat;
|
||||
|
||||
/// NoImplicitFloat - This flag is enabled when the -no-implicit-float flag is
|
||||
/// specified on the command line. When this flag is on, the code generator
|
||||
/// won't generate any implicit floating point instructions. I.e., no XMM or
|
||||
/// x87 or vectorized memcpy/memmove instructions. This is for X86 only.
|
||||
extern bool NoImplicitFloat;
|
||||
|
||||
/// NoZerosInBSS - By default some codegens place zero-initialized data to
|
||||
/// .bss section. This flag disables such behaviour (necessary, e.g. for
|
||||
/// crt*.o compiling).
|
||||
@ -117,10 +111,6 @@ namespace llvm {
|
||||
/// wth earlier copy coalescing.
|
||||
extern bool StrongPHIElim;
|
||||
|
||||
/// DisableRedZone - This flag disables use of the "Red Zone" on
|
||||
/// targets which would otherwise have one.
|
||||
extern bool DisableRedZone;
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "llvm/Support/InstVisitor.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
STATISTIC(TotalInsts , "Number of instructions (of all types)");
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "llvm/ADT/DepthFirstIterator.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include <algorithm>
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
char LoopInfo::ID = 0;
|
||||
|
@ -80,7 +80,6 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/ADT/Statistic.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include <ostream>
|
||||
#include <algorithm>
|
||||
using namespace llvm;
|
||||
|
||||
@ -2463,24 +2462,15 @@ void ScalarEvolution::forgetLoopPHIs(const Loop *L) {
|
||||
ScalarEvolution::BackedgeTakenInfo
|
||||
ScalarEvolution::ComputeBackedgeTakenCount(const Loop *L) {
|
||||
// If the loop has a non-one exit block count, we can't analyze it.
|
||||
SmallVector<BasicBlock*, 8> ExitBlocks;
|
||||
L->getExitBlocks(ExitBlocks);
|
||||
if (ExitBlocks.size() != 1) return UnknownValue;
|
||||
BasicBlock *ExitBlock = L->getExitBlock();
|
||||
if (!ExitBlock)
|
||||
return UnknownValue;
|
||||
|
||||
// Okay, there is one exit block. Try to find the condition that causes the
|
||||
// loop to be exited.
|
||||
BasicBlock *ExitBlock = ExitBlocks[0];
|
||||
|
||||
BasicBlock *ExitingBlock = 0;
|
||||
for (pred_iterator PI = pred_begin(ExitBlock), E = pred_end(ExitBlock);
|
||||
PI != E; ++PI)
|
||||
if (L->contains(*PI)) {
|
||||
if (ExitingBlock == 0)
|
||||
ExitingBlock = *PI;
|
||||
else
|
||||
return UnknownValue; // More than one block exiting!
|
||||
}
|
||||
assert(ExitingBlock && "No exits from loop, something is broken!");
|
||||
BasicBlock *ExitingBlock = L->getExitingBlock();
|
||||
if (!ExitingBlock)
|
||||
return UnknownValue; // More than one block exiting!
|
||||
|
||||
// Okay, we've computed the exiting block. See what condition causes us to
|
||||
// exit.
|
||||
|
@ -644,3 +644,16 @@ Value *SCEVExpander::expand(const SCEV *S) {
|
||||
InsertedExpressions[S] = V;
|
||||
return V;
|
||||
}
|
||||
|
||||
/// getOrInsertCanonicalInductionVariable - This method returns the
|
||||
/// canonical induction variable of the specified type for the specified
|
||||
/// loop (inserting one if there is none). A canonical induction variable
|
||||
/// starts at zero and steps by one on each iteration.
|
||||
Value *
|
||||
SCEVExpander::getOrInsertCanonicalInductionVariable(const Loop *L,
|
||||
const Type *Ty) {
|
||||
assert(Ty->isInteger() && "Can only insert integer induction variables!");
|
||||
SCEVHandle H = SE.getAddRecExpr(SE.getIntegerSCEV(0, Ty),
|
||||
SE.getIntegerSCEV(1, Ty), L);
|
||||
return expand(H);
|
||||
}
|
||||
|
@ -771,7 +771,7 @@ bool llvm::CannotBeNegativeZero(const Value *V, unsigned Depth) {
|
||||
if (I == 0) return false;
|
||||
|
||||
// (add x, 0.0) is guaranteed to return +0.0, not -0.0.
|
||||
if (I->getOpcode() == Instruction::Add &&
|
||||
if (I->getOpcode() == Instruction::FAdd &&
|
||||
isa<ConstantFP>(I->getOperand(1)) &&
|
||||
cast<ConstantFP>(I->getOperand(1))->isNullValue())
|
||||
return true;
|
||||
|
@ -547,6 +547,8 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(optsize);
|
||||
KEYWORD(ssp);
|
||||
KEYWORD(sspreq);
|
||||
KEYWORD(noredzone);
|
||||
KEYWORD(noimplicitfloat);
|
||||
|
||||
KEYWORD(type);
|
||||
KEYWORD(opaque);
|
||||
@ -590,7 +592,9 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
if (Len == strlen(#STR) && !memcmp(StartChar, #STR, strlen(#STR))) { \
|
||||
UIntVal = Instruction::Enum; return lltok::kw_##STR; }
|
||||
|
||||
INSTKEYWORD(add, Add); INSTKEYWORD(sub, Sub); INSTKEYWORD(mul, Mul);
|
||||
INSTKEYWORD(add, Add); INSTKEYWORD(fadd, FAdd);
|
||||
INSTKEYWORD(sub, Sub); INSTKEYWORD(fsub, FSub);
|
||||
INSTKEYWORD(mul, Mul); INSTKEYWORD(fmul, FMul);
|
||||
INSTKEYWORD(udiv, UDiv); INSTKEYWORD(sdiv, SDiv); INSTKEYWORD(fdiv, FDiv);
|
||||
INSTKEYWORD(urem, URem); INSTKEYWORD(srem, SRem); INSTKEYWORD(frem, FRem);
|
||||
INSTKEYWORD(shl, Shl); INSTKEYWORD(lshr, LShr); INSTKEYWORD(ashr, AShr);
|
||||
|
@ -712,25 +712,26 @@ bool LLParser::ParseOptionalAttrs(unsigned &Attrs, unsigned AttrKind) {
|
||||
return Error(AttrLoc, "invalid use of parameter-only attribute");
|
||||
|
||||
return false;
|
||||
case lltok::kw_zeroext: Attrs |= Attribute::ZExt; break;
|
||||
case lltok::kw_signext: Attrs |= Attribute::SExt; break;
|
||||
case lltok::kw_inreg: Attrs |= Attribute::InReg; break;
|
||||
case lltok::kw_sret: Attrs |= Attribute::StructRet; break;
|
||||
case lltok::kw_noalias: Attrs |= Attribute::NoAlias; break;
|
||||
case lltok::kw_nocapture: Attrs |= Attribute::NoCapture; break;
|
||||
case lltok::kw_byval: Attrs |= Attribute::ByVal; break;
|
||||
case lltok::kw_nest: Attrs |= Attribute::Nest; break;
|
||||
|
||||
case lltok::kw_noreturn: Attrs |= Attribute::NoReturn; break;
|
||||
case lltok::kw_nounwind: Attrs |= Attribute::NoUnwind; break;
|
||||
case lltok::kw_noinline: Attrs |= Attribute::NoInline; break;
|
||||
case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break;
|
||||
case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break;
|
||||
case lltok::kw_alwaysinline: Attrs |= Attribute::AlwaysInline; break;
|
||||
case lltok::kw_optsize: Attrs |= Attribute::OptimizeForSize; break;
|
||||
case lltok::kw_ssp: Attrs |= Attribute::StackProtect; break;
|
||||
case lltok::kw_sspreq: Attrs |= Attribute::StackProtectReq; break;
|
||||
case lltok::kw_zeroext: Attrs |= Attribute::ZExt; break;
|
||||
case lltok::kw_signext: Attrs |= Attribute::SExt; break;
|
||||
case lltok::kw_inreg: Attrs |= Attribute::InReg; break;
|
||||
case lltok::kw_sret: Attrs |= Attribute::StructRet; break;
|
||||
case lltok::kw_noalias: Attrs |= Attribute::NoAlias; break;
|
||||
case lltok::kw_nocapture: Attrs |= Attribute::NoCapture; break;
|
||||
case lltok::kw_byval: Attrs |= Attribute::ByVal; break;
|
||||
case lltok::kw_nest: Attrs |= Attribute::Nest; break;
|
||||
|
||||
case lltok::kw_noreturn: Attrs |= Attribute::NoReturn; break;
|
||||
case lltok::kw_nounwind: Attrs |= Attribute::NoUnwind; break;
|
||||
case lltok::kw_noinline: Attrs |= Attribute::NoInline; break;
|
||||
case lltok::kw_readnone: Attrs |= Attribute::ReadNone; break;
|
||||
case lltok::kw_readonly: Attrs |= Attribute::ReadOnly; break;
|
||||
case lltok::kw_alwaysinline: Attrs |= Attribute::AlwaysInline; break;
|
||||
case lltok::kw_optsize: Attrs |= Attribute::OptimizeForSize; break;
|
||||
case lltok::kw_ssp: Attrs |= Attribute::StackProtect; break;
|
||||
case lltok::kw_sspreq: Attrs |= Attribute::StackProtectReq; break;
|
||||
case lltok::kw_noredzone: Attrs |= Attribute::NoRedZone; break;
|
||||
case lltok::kw_noimplicitfloat: Attrs |= Attribute::NoImplicitFloat; break;
|
||||
|
||||
case lltok::kw_align: {
|
||||
unsigned Alignment;
|
||||
@ -1835,8 +1836,11 @@ bool LLParser::ParseValID(ValID &ID) {
|
||||
|
||||
// Binary Operators.
|
||||
case lltok::kw_add:
|
||||
case lltok::kw_fadd:
|
||||
case lltok::kw_sub:
|
||||
case lltok::kw_fsub:
|
||||
case lltok::kw_mul:
|
||||
case lltok::kw_fmul:
|
||||
case lltok::kw_udiv:
|
||||
case lltok::kw_sdiv:
|
||||
case lltok::kw_fdiv:
|
||||
@ -2400,8 +2404,13 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
|
||||
// Binary Operators.
|
||||
case lltok::kw_add:
|
||||
case lltok::kw_sub:
|
||||
case lltok::kw_mul: return ParseArithmetic(Inst, PFS, KeywordVal, 0);
|
||||
|
||||
case lltok::kw_mul:
|
||||
// API compatibility: Accept either integer or floating-point types.
|
||||
return ParseArithmetic(Inst, PFS, KeywordVal, 0);
|
||||
case lltok::kw_fadd:
|
||||
case lltok::kw_fsub:
|
||||
case lltok::kw_fmul: return ParseArithmetic(Inst, PFS, KeywordVal, 2);
|
||||
|
||||
case lltok::kw_udiv:
|
||||
case lltok::kw_sdiv:
|
||||
case lltok::kw_urem:
|
||||
|
@ -80,6 +80,8 @@ namespace lltok {
|
||||
kw_optsize,
|
||||
kw_ssp,
|
||||
kw_sspreq,
|
||||
kw_noredzone,
|
||||
kw_noimplicitfloat,
|
||||
|
||||
kw_type,
|
||||
kw_opaque,
|
||||
@ -89,7 +91,8 @@ namespace lltok {
|
||||
kw_ueq, kw_une,
|
||||
|
||||
// Instruction Opcodes (Opcode in UIntVal).
|
||||
kw_add, kw_sub, kw_mul, kw_udiv, kw_sdiv, kw_fdiv,
|
||||
kw_add, kw_fadd, kw_sub, kw_fsub, kw_mul, kw_fmul,
|
||||
kw_udiv, kw_sdiv, kw_fdiv,
|
||||
kw_urem, kw_srem, kw_frem, kw_shl, kw_lshr, kw_ashr,
|
||||
kw_and, kw_or, kw_xor, kw_icmp, kw_fcmp, kw_vicmp, kw_vfcmp,
|
||||
|
||||
|
@ -104,9 +104,12 @@ static int GetDecodedCastOpcode(unsigned Val) {
|
||||
static int GetDecodedBinaryOpcode(unsigned Val, const Type *Ty) {
|
||||
switch (Val) {
|
||||
default: return -1;
|
||||
case bitc::BINOP_ADD: return Instruction::Add;
|
||||
case bitc::BINOP_SUB: return Instruction::Sub;
|
||||
case bitc::BINOP_MUL: return Instruction::Mul;
|
||||
case bitc::BINOP_ADD:
|
||||
return Ty->isFPOrFPVector() ? Instruction::FAdd : Instruction::Add;
|
||||
case bitc::BINOP_SUB:
|
||||
return Ty->isFPOrFPVector() ? Instruction::FSub : Instruction::Sub;
|
||||
case bitc::BINOP_MUL:
|
||||
return Ty->isFPOrFPVector() ? Instruction::FMul : Instruction::Mul;
|
||||
case bitc::BINOP_UDIV: return Instruction::UDiv;
|
||||
case bitc::BINOP_SDIV:
|
||||
return Ty->isFPOrFPVector() ? Instruction::FDiv : Instruction::SDiv;
|
||||
|
@ -77,9 +77,12 @@ static unsigned GetEncodedCastOpcode(unsigned Opcode) {
|
||||
static unsigned GetEncodedBinaryOpcode(unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
default: assert(0 && "Unknown binary instruction!");
|
||||
case Instruction::Add: return bitc::BINOP_ADD;
|
||||
case Instruction::Sub: return bitc::BINOP_SUB;
|
||||
case Instruction::Mul: return bitc::BINOP_MUL;
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd: return bitc::BINOP_ADD;
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub: return bitc::BINOP_SUB;
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul: return bitc::BINOP_MUL;
|
||||
case Instruction::UDiv: return bitc::BINOP_UDIV;
|
||||
case Instruction::FDiv:
|
||||
case Instruction::SDiv: return bitc::BINOP_SDIV;
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
static TimerGroup &getDwarfTimerGroup() {
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetFrameInfo.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include <ostream>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
186
lib/CodeGen/ELF.h
Normal file
186
lib/CodeGen/ELF.h
Normal file
@ -0,0 +1,186 @@
|
||||
//===-- lib/CodeGen/ELF.h - ELF constants and data structures ---*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This header contains common, non-processor-specific data structures and
|
||||
// constants for the ELF file format.
|
||||
//
|
||||
// The details of the ELF32 bits in this file are largely based on
|
||||
// the Tool Interface Standard (TIS) Executable and Linking Format
|
||||
// (ELF) Specification Version 1.2, May 1995. The ELF64 stuff is not
|
||||
// standardized, as far as I can tell. It was largely based on information
|
||||
// I found in OpenBSD header files.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef CODEGEN_ELF_H
|
||||
#define CODEGEN_ELF_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace llvm {
|
||||
class GlobalVariable;
|
||||
|
||||
// Identification Indexes
|
||||
enum {
|
||||
EI_MAG0 = 0,
|
||||
EI_MAG1 = 1,
|
||||
EI_MAG2 = 2,
|
||||
EI_MAG3 = 3
|
||||
};
|
||||
|
||||
// File types
|
||||
enum {
|
||||
ET_NONE = 0, // No file type
|
||||
ET_REL = 1, // Relocatable file
|
||||
ET_EXEC = 2, // Executable file
|
||||
ET_DYN = 3, // Shared object file
|
||||
ET_CORE = 4, // Core file
|
||||
ET_LOPROC = 0xff00, // Beginning of processor-specific codes
|
||||
ET_HIPROC = 0xffff // Processor-specific
|
||||
};
|
||||
|
||||
// Object file classes.
|
||||
enum {
|
||||
ELFCLASS32 = 1, // 32-bit object file
|
||||
ELFCLASS64 = 2 // 64-bit object file
|
||||
};
|
||||
|
||||
// Object file byte orderings.
|
||||
enum {
|
||||
ELFDATA2LSB = 1, // Little-endian object file
|
||||
ELFDATA2MSB = 2 // Big-endian object file
|
||||
};
|
||||
|
||||
// Versioning
|
||||
enum {
|
||||
EV_NONE = 0,
|
||||
EV_CURRENT = 1
|
||||
};
|
||||
|
||||
/// ELFSection - This struct contains information about each section that is
|
||||
/// emitted to the file. This is eventually turned into the section header
|
||||
/// table at the end of the file.
|
||||
struct ELFSection {
|
||||
|
||||
// ELF specific fields
|
||||
std::string Name; // Name of the section.
|
||||
unsigned NameIdx; // Index in .shstrtab of name, once emitted.
|
||||
unsigned Type;
|
||||
unsigned Flags;
|
||||
uint64_t Addr;
|
||||
unsigned Offset;
|
||||
unsigned Size;
|
||||
unsigned Link;
|
||||
unsigned Info;
|
||||
unsigned Align;
|
||||
unsigned EntSize;
|
||||
|
||||
// Section Header Flags
|
||||
enum {
|
||||
SHF_WRITE = 1 << 0, // Writable
|
||||
SHF_ALLOC = 1 << 1, // Mapped into the process addr space
|
||||
SHF_EXECINSTR = 1 << 2, // Executable
|
||||
SHF_MERGE = 1 << 4, // Might be merged if equal
|
||||
SHF_STRINGS = 1 << 5, // Contains null-terminated strings
|
||||
SHF_INFO_LINK = 1 << 6, // 'sh_info' contains SHT index
|
||||
SHF_LINK_ORDER = 1 << 7, // Preserve order after combining
|
||||
SHF_OS_NONCONFORMING = 1 << 8, // nonstandard OS support required
|
||||
SHF_GROUP = 1 << 9, // Section is a member of a group
|
||||
SHF_TLS = 1 << 10 // Section holds thread-local data
|
||||
};
|
||||
|
||||
// Section Types
|
||||
enum {
|
||||
SHT_NULL = 0, // No associated section (inactive entry).
|
||||
SHT_PROGBITS = 1, // Program-defined contents.
|
||||
SHT_SYMTAB = 2, // Symbol table.
|
||||
SHT_STRTAB = 3, // String table.
|
||||
SHT_RELA = 4, // Relocation entries; explicit addends.
|
||||
SHT_HASH = 5, // Symbol hash table.
|
||||
SHT_DYNAMIC = 6, // Information for dynamic linking.
|
||||
SHT_NOTE = 7, // Information about the file.
|
||||
SHT_NOBITS = 8, // Data occupies no space in the file.
|
||||
SHT_REL = 9, // Relocation entries; no explicit addends.
|
||||
SHT_SHLIB = 10, // Reserved.
|
||||
SHT_DYNSYM = 11, // Symbol table.
|
||||
SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type.
|
||||
SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type.
|
||||
SHT_LOUSER = 0x80000000, // Lowest type reserved for applications.
|
||||
SHT_HIUSER = 0xffffffff // Highest type reserved for applications.
|
||||
};
|
||||
|
||||
// Special section indices.
|
||||
enum {
|
||||
SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless
|
||||
SHN_LORESERVE = 0xff00, // Lowest reserved index
|
||||
SHN_LOPROC = 0xff00, // Lowest processor-specific index
|
||||
SHN_HIPROC = 0xff1f, // Highest processor-specific index
|
||||
SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation
|
||||
SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables
|
||||
SHN_HIRESERVE = 0xffff // Highest reserved index
|
||||
};
|
||||
|
||||
/// SectionIdx - The number of the section in the Section Table.
|
||||
unsigned short SectionIdx;
|
||||
|
||||
/// SectionData - The actual data for this section which we are building
|
||||
/// up for emission to the file.
|
||||
std::vector<unsigned char> SectionData;
|
||||
|
||||
ELFSection(const std::string &name)
|
||||
: Name(name), Type(0), Flags(0), Addr(0), Offset(0), Size(0),
|
||||
Link(0), Info(0), Align(0), EntSize(0) {}
|
||||
};
|
||||
|
||||
/// ELFSym - This struct contains information about each symbol that is
|
||||
/// added to logical symbol table for the module. This is eventually
|
||||
/// turned into a real symbol table in the file.
|
||||
struct ELFSym {
|
||||
const GlobalValue *GV; // The global value this corresponds to.
|
||||
|
||||
// ELF specific fields
|
||||
unsigned NameIdx; // Index in .strtab of name, once emitted.
|
||||
uint64_t Value;
|
||||
unsigned Size;
|
||||
uint8_t Info;
|
||||
uint8_t Other;
|
||||
unsigned short SectionIdx;
|
||||
|
||||
enum {
|
||||
STB_LOCAL = 0,
|
||||
STB_GLOBAL = 1,
|
||||
STB_WEAK = 2
|
||||
};
|
||||
|
||||
enum {
|
||||
STT_NOTYPE = 0,
|
||||
STT_OBJECT = 1,
|
||||
STT_FUNC = 2,
|
||||
STT_SECTION = 3,
|
||||
STT_FILE = 4
|
||||
};
|
||||
|
||||
ELFSym(const GlobalValue *gv) : GV(gv), Value(0),
|
||||
Size(0), Info(0), Other(0),
|
||||
SectionIdx(ELFSection::SHN_UNDEF) {}
|
||||
|
||||
void SetBind(unsigned X) {
|
||||
assert(X == (X & 0xF) && "Bind value out of range!");
|
||||
Info = (Info & 0x0F) | (X << 4);
|
||||
}
|
||||
void SetType(unsigned X) {
|
||||
assert(X == (X & 0xF) && "Type value out of range!");
|
||||
Info = (Info & 0xF0) | X;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
@ -7,17 +7,17 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#define DEBUG_TYPE "elfce"
|
||||
|
||||
#include "ELFCodeEmitter.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
||||
#include "llvm/Target/TargetAsmInfo.h"
|
||||
#include "llvm/Target/TargetData.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Support/Mangler.h"
|
||||
#include "llvm/Support/OutputBuffer.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ELFCodeEmitter Implementation
|
||||
@ -27,67 +27,87 @@ namespace llvm {
|
||||
|
||||
/// startFunction - This callback is invoked when a new machine function is
|
||||
/// about to be emitted.
|
||||
void ELFCodeEmitter::startFunction(MachineFunction &F) {
|
||||
// Align the output buffer to the appropriate alignment.
|
||||
unsigned Align = 16; // FIXME: GENERICIZE!!
|
||||
void ELFCodeEmitter::startFunction(MachineFunction &MF) {
|
||||
const TargetData *TD = TM.getTargetData();
|
||||
const Function *F = MF.getFunction();
|
||||
|
||||
// Align the output buffer to the appropriate alignment, power of 2.
|
||||
unsigned FnAlign = F->getAlignment();
|
||||
unsigned TDAlign = TD->getPrefTypeAlignment(F->getType());
|
||||
unsigned Align = std::max(FnAlign, TDAlign);
|
||||
assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
|
||||
|
||||
// Get the ELF Section that this function belongs in.
|
||||
ES = &EW.getSection(".text", ELFWriter::ELFSection::SHT_PROGBITS,
|
||||
ELFWriter::ELFSection::SHF_EXECINSTR |
|
||||
ELFWriter::ELFSection::SHF_ALLOC);
|
||||
OutBuffer = &ES->SectionData;
|
||||
cerr << "FIXME: This code needs to be updated for changes in the "
|
||||
<< "CodeEmitter interfaces. In particular, this should set "
|
||||
<< "BufferBegin/BufferEnd/CurBufferPtr, not deal with OutBuffer!";
|
||||
abort();
|
||||
ES = &EW.getTextSection();
|
||||
|
||||
// FIXME: better memory management, this will be replaced by BinaryObjects
|
||||
ES->SectionData.reserve(4096);
|
||||
BufferBegin = &ES->SectionData[0];
|
||||
BufferEnd = BufferBegin + ES->SectionData.capacity();
|
||||
|
||||
// Upgrade the section alignment if required.
|
||||
if (ES->Align < Align) ES->Align = Align;
|
||||
|
||||
// Add padding zeros to the end of the buffer to make sure that the
|
||||
// function will start on the correct byte alignment within the section.
|
||||
OutputBuffer OB(*OutBuffer,
|
||||
TM.getTargetData()->getPointerSizeInBits() == 64,
|
||||
TM.getTargetData()->isLittleEndian());
|
||||
OB.align(Align);
|
||||
FnStart = OutBuffer->size();
|
||||
// Round the size up to the correct alignment for starting the new function.
|
||||
ES->Size = (ES->Size + (Align-1)) & (-Align);
|
||||
|
||||
// Snaity check on allocated space for text section
|
||||
assert( ES->Size < 4096 && "no more space in TextSection" );
|
||||
|
||||
// FIXME: Using ES->Size directly here instead of calculating it from the
|
||||
// output buffer size (impossible because the code emitter deals only in raw
|
||||
// bytes) forces us to manually synchronize size and write padding zero bytes
|
||||
// to the output buffer for all non-text sections. For text sections, we do
|
||||
// not synchonize the output buffer, and we just blow up if anyone tries to
|
||||
// write non-code to it. An assert should probably be added to
|
||||
// AddSymbolToSection to prevent calling it on the text section.
|
||||
CurBufferPtr = BufferBegin + ES->Size;
|
||||
|
||||
// Record function start address relative to BufferBegin
|
||||
FnStartPtr = CurBufferPtr;
|
||||
}
|
||||
|
||||
/// finishFunction - This callback is invoked after the function is completely
|
||||
/// finished.
|
||||
bool ELFCodeEmitter::finishFunction(MachineFunction &F) {
|
||||
// We now know the size of the function, add a symbol to represent it.
|
||||
ELFWriter::ELFSym FnSym(F.getFunction());
|
||||
bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
|
||||
// Add a symbol to represent the function.
|
||||
ELFSym FnSym(MF.getFunction());
|
||||
|
||||
// Figure out the binding (linkage) of the symbol.
|
||||
switch (F.getFunction()->getLinkage()) {
|
||||
switch (MF.getFunction()->getLinkage()) {
|
||||
default:
|
||||
// appending linkage is illegal for functions.
|
||||
assert(0 && "Unknown linkage type!");
|
||||
case GlobalValue::ExternalLinkage:
|
||||
FnSym.SetBind(ELFWriter::ELFSym::STB_GLOBAL);
|
||||
FnSym.SetBind(ELFSym::STB_GLOBAL);
|
||||
break;
|
||||
case GlobalValue::LinkOnceAnyLinkage:
|
||||
case GlobalValue::LinkOnceODRLinkage:
|
||||
case GlobalValue::WeakAnyLinkage:
|
||||
case GlobalValue::WeakODRLinkage:
|
||||
FnSym.SetBind(ELFWriter::ELFSym::STB_WEAK);
|
||||
FnSym.SetBind(ELFSym::STB_WEAK);
|
||||
break;
|
||||
case GlobalValue::PrivateLinkage:
|
||||
assert (0 && "PrivateLinkage should not be in the symbol table.");
|
||||
case GlobalValue::InternalLinkage:
|
||||
FnSym.SetBind(ELFWriter::ELFSym::STB_LOCAL);
|
||||
FnSym.SetBind(ELFSym::STB_LOCAL);
|
||||
break;
|
||||
}
|
||||
|
||||
ES->Size = OutBuffer->size();
|
||||
// Set the symbol type as a function
|
||||
FnSym.SetType(ELFSym::STT_FUNC);
|
||||
|
||||
FnSym.SetType(ELFWriter::ELFSym::STT_FUNC);
|
||||
FnSym.SectionIdx = ES->SectionIdx;
|
||||
FnSym.Value = FnStart; // Value = Offset from start of Section.
|
||||
FnSym.Size = OutBuffer->size()-FnStart;
|
||||
FnSym.Size = CurBufferPtr-FnStartPtr;
|
||||
|
||||
// Offset from start of Section
|
||||
FnSym.Value = FnStartPtr-BufferBegin;
|
||||
|
||||
// Finally, add it to the symtab.
|
||||
EW.SymbolTable.push_back(FnSym);
|
||||
|
||||
// Update Section Size
|
||||
ES->Size = CurBufferPtr - BufferBegin;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -21,11 +21,10 @@ namespace llvm {
|
||||
class ELFCodeEmitter : public MachineCodeEmitter {
|
||||
ELFWriter &EW;
|
||||
TargetMachine &TM;
|
||||
ELFWriter::ELFSection *ES; // Section to write to.
|
||||
std::vector<unsigned char> *OutBuffer;
|
||||
size_t FnStart;
|
||||
ELFSection *ES; // Section to write to.
|
||||
uint8_t *FnStartPtr;
|
||||
public:
|
||||
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM), OutBuffer(0) {}
|
||||
explicit ELFCodeEmitter(ELFWriter &ew) : EW(ew), TM(EW.TM) {}
|
||||
|
||||
void startFunction(MachineFunction &F);
|
||||
bool finishFunction(MachineFunction &F);
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include "ELFWriter.h"
|
||||
#include "ELFCodeEmitter.h"
|
||||
#include "ELF.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/PassManager.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
@ -67,7 +68,8 @@ MachineCodeEmitter *llvm::AddELFWriter(PassManagerBase &PM,
|
||||
|
||||
ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
|
||||
: MachineFunctionPass(&ID), O(o), TM(tm) {
|
||||
e_flags = 0; // e_flags defaults to 0, no flags.
|
||||
e_flags = 0; // e_flags defaults to 0, no flags.
|
||||
e_machine = TM.getELFWriterInfo()->getEMachine();
|
||||
|
||||
is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64;
|
||||
isLittleEndian = TM.getTargetData()->isLittleEndian();
|
||||
@ -90,24 +92,39 @@ bool ELFWriter::doInitialization(Module &M) {
|
||||
std::vector<unsigned char> &FH = FileHeader;
|
||||
OutputBuffer FHOut(FH, is64Bit, isLittleEndian);
|
||||
|
||||
FHOut.outbyte(0x7F); // EI_MAG0
|
||||
FHOut.outbyte('E'); // EI_MAG1
|
||||
FHOut.outbyte('L'); // EI_MAG2
|
||||
FHOut.outbyte('F'); // EI_MAG3
|
||||
FHOut.outbyte(is64Bit ? 2 : 1); // EI_CLASS
|
||||
FHOut.outbyte(isLittleEndian ? 1 : 2); // EI_DATA
|
||||
FHOut.outbyte(1); // EI_VERSION
|
||||
FH.resize(16); // EI_PAD up to 16 bytes.
|
||||
unsigned ElfClass = is64Bit ? ELFCLASS64 : ELFCLASS32;
|
||||
unsigned ElfEndian = isLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
|
||||
|
||||
// This should change for shared objects.
|
||||
FHOut.outhalf(1); // e_type = ET_REL
|
||||
FHOut.outhalf(TM.getELFWriterInfo()->getEMachine()); // target-defined
|
||||
FHOut.outword(1); // e_version = 1
|
||||
FHOut.outaddr(0); // e_entry = 0 -> no entry point in .o file
|
||||
FHOut.outaddr(0); // e_phoff = 0 -> no program header for .o
|
||||
// ELF Header
|
||||
// ----------
|
||||
// Fields e_shnum e_shstrndx are only known after all section have
|
||||
// been emitted. They locations in the ouput buffer are recorded so
|
||||
// to be patched up later.
|
||||
//
|
||||
// Note
|
||||
// ----
|
||||
// FHOut.outaddr method behaves differently for ELF32 and ELF64 writing
|
||||
// 4 bytes in the former and 8 in the last for *_off and *_addr elf types
|
||||
|
||||
ELFHeader_e_shoff_Offset = FH.size();
|
||||
FHOut.outaddr(0); // e_shoff
|
||||
FHOut.outbyte(0x7f); // e_ident[EI_MAG0]
|
||||
FHOut.outbyte('E'); // e_ident[EI_MAG1]
|
||||
FHOut.outbyte('L'); // e_ident[EI_MAG2]
|
||||
FHOut.outbyte('F'); // e_ident[EI_MAG3]
|
||||
|
||||
FHOut.outbyte(ElfClass); // e_ident[EI_CLASS]
|
||||
FHOut.outbyte(ElfEndian); // e_ident[EI_DATA]
|
||||
FHOut.outbyte(EV_CURRENT); // e_ident[EI_VERSION]
|
||||
|
||||
FH.resize(16); // e_ident[EI_NIDENT-EI_PAD]
|
||||
|
||||
FHOut.outhalf(ET_REL); // e_type
|
||||
FHOut.outhalf(e_machine); // e_machine = target
|
||||
FHOut.outword(EV_CURRENT); // e_version
|
||||
FHOut.outaddr(0); // e_entry = 0 -> no entry point in .o file
|
||||
FHOut.outaddr(0); // e_phoff = 0 -> no program header for .o
|
||||
|
||||
ELFHdr_e_shoff_Offset = FH.size();
|
||||
FHOut.outaddr(0); // e_shoff = sec hdr table off in bytes
|
||||
FHOut.outword(e_flags); // e_flags = whatever the target wants
|
||||
|
||||
FHOut.outhalf(is64Bit ? 64 : 52); // e_ehsize = ELF header size
|
||||
@ -115,14 +132,16 @@ bool ELFWriter::doInitialization(Module &M) {
|
||||
FHOut.outhalf(0); // e_phnum = # prog header entries = 0
|
||||
FHOut.outhalf(is64Bit ? 64 : 40); // e_shentsize = sect hdr entry size
|
||||
|
||||
// e_shnum = # of section header ents
|
||||
ELFHdr_e_shnum_Offset = FH.size();
|
||||
FHOut.outhalf(0);
|
||||
|
||||
ELFHeader_e_shnum_Offset = FH.size();
|
||||
FHOut.outhalf(0); // e_shnum = # of section header ents
|
||||
ELFHeader_e_shstrndx_Offset = FH.size();
|
||||
FHOut.outhalf(0); // e_shstrndx = Section # of '.shstrtab'
|
||||
// e_shstrndx = Section # of '.shstrtab'
|
||||
ELFHdr_e_shstrndx_Offset = FH.size();
|
||||
FHOut.outhalf(0);
|
||||
|
||||
// Add the null section, which is required to be first in the file.
|
||||
getSection("", 0, 0);
|
||||
getSection("", ELFSection::SHT_NULL, 0);
|
||||
|
||||
// Start up the symbol table. The first entry in the symtab is the null
|
||||
// entry.
|
||||
@ -334,7 +353,7 @@ void ELFWriter::EmitSectionTableStringTable() {
|
||||
// Now that we know which section number is the .shstrtab section, update the
|
||||
// e_shstrndx entry in the ELF header.
|
||||
OutputBuffer FHOut(FileHeader, is64Bit, isLittleEndian);
|
||||
FHOut.fixhalf(SHStrTab.SectionIdx, ELFHeader_e_shstrndx_Offset);
|
||||
FHOut.fixhalf(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset);
|
||||
|
||||
// Set the NameIdx of each section in the string table and emit the bytes for
|
||||
// the string table.
|
||||
@ -386,11 +405,11 @@ void ELFWriter::OutputSectionsAndSectionTable() {
|
||||
// Now that we know where all of the sections will be emitted, set the e_shnum
|
||||
// entry in the ELF header.
|
||||
OutputBuffer FHOut(FileHeader, is64Bit, isLittleEndian);
|
||||
FHOut.fixhalf(NumSections, ELFHeader_e_shnum_Offset);
|
||||
FHOut.fixhalf(NumSections, ELFHdr_e_shnum_Offset);
|
||||
|
||||
// Now that we know the offset in the file of the section table, update the
|
||||
// e_shoff address in the ELF header.
|
||||
FHOut.fixaddr(FileOff, ELFHeader_e_shoff_Offset);
|
||||
FHOut.fixaddr(FileOff, ELFHdr_e_shoff_Offset);
|
||||
|
||||
// Now that we know all of the data in the file header, emit it and all of the
|
||||
// sections!
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define ELFWRITER_H
|
||||
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "ELF.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
@ -82,10 +83,8 @@ namespace llvm {
|
||||
/// doInitialization - Emit the file header and all of the global variables
|
||||
/// for the module to the ELF file.
|
||||
bool doInitialization(Module &M);
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF);
|
||||
|
||||
|
||||
/// doFinalization - Now that the module has been completely processed, emit
|
||||
/// the ELF file to 'O'.
|
||||
bool doFinalization(Module &M);
|
||||
@ -96,53 +95,6 @@ namespace llvm {
|
||||
// as well!).
|
||||
DataBuffer FileHeader;
|
||||
|
||||
/// ELFSection - This struct contains information about each section that is
|
||||
/// emitted to the file. This is eventually turned into the section header
|
||||
/// table at the end of the file.
|
||||
struct ELFSection {
|
||||
std::string Name; // Name of the section.
|
||||
unsigned NameIdx; // Index in .shstrtab of name, once emitted.
|
||||
unsigned Type;
|
||||
unsigned Flags;
|
||||
uint64_t Addr;
|
||||
unsigned Offset;
|
||||
unsigned Size;
|
||||
unsigned Link;
|
||||
unsigned Info;
|
||||
unsigned Align;
|
||||
unsigned EntSize;
|
||||
|
||||
/// SectionIdx - The number of the section in the Section Table.
|
||||
///
|
||||
unsigned short SectionIdx;
|
||||
|
||||
/// SectionData - The actual data for this section which we are building
|
||||
/// up for emission to the file.
|
||||
DataBuffer SectionData;
|
||||
|
||||
enum { SHT_NULL = 0, SHT_PROGBITS = 1, SHT_SYMTAB = 2, SHT_STRTAB = 3,
|
||||
SHT_RELA = 4, SHT_HASH = 5, SHT_DYNAMIC = 6, SHT_NOTE = 7,
|
||||
SHT_NOBITS = 8, SHT_REL = 9, SHT_SHLIB = 10, SHT_DYNSYM = 11 };
|
||||
enum { SHN_UNDEF = 0, SHN_ABS = 0xFFF1, SHN_COMMON = 0xFFF2 };
|
||||
enum { // SHF - ELF Section Header Flags
|
||||
SHF_WRITE = 1 << 0, // Writable
|
||||
SHF_ALLOC = 1 << 1, // Mapped into the process addr space
|
||||
SHF_EXECINSTR = 1 << 2, // Executable
|
||||
SHF_MERGE = 1 << 4, // Might be merged if equal
|
||||
SHF_STRINGS = 1 << 5, // Contains null-terminated strings
|
||||
SHF_INFO_LINK = 1 << 6, // 'sh_info' contains SHT index
|
||||
SHF_LINK_ORDER = 1 << 7, // Preserve order after combining
|
||||
SHF_OS_NONCONFORMING = 1 << 8, // nonstandard OS support required
|
||||
SHF_GROUP = 1 << 9, // Section is a member of a group
|
||||
SHF_TLS = 1 << 10 // Section holds thread-local data
|
||||
};
|
||||
|
||||
ELFSection(const std::string &name)
|
||||
: Name(name), Type(0), Flags(0), Addr(0), Offset(0), Size(0),
|
||||
Link(0), Info(0), Align(0), EntSize(0) {
|
||||
}
|
||||
};
|
||||
|
||||
/// SectionList - This is the list of sections that we have emitted to the
|
||||
/// file. Once the file has been completely built, the section header table
|
||||
/// is constructed from this info.
|
||||
@ -165,9 +117,15 @@ namespace llvm {
|
||||
SN->SectionIdx = NumSections++;
|
||||
SN->Type = Type;
|
||||
SN->Flags = Flags;
|
||||
SN->Link = ELFSection::SHN_UNDEF;
|
||||
return *SN;
|
||||
}
|
||||
|
||||
ELFSection &getTextSection() {
|
||||
return getSection(".text", ELFSection::SHT_PROGBITS,
|
||||
ELFSection::SHF_EXECINSTR | ELFSection::SHF_ALLOC);
|
||||
}
|
||||
|
||||
ELFSection &getDataSection() {
|
||||
return getSection(".data", ELFSection::SHT_PROGBITS,
|
||||
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
|
||||
@ -177,34 +135,6 @@ namespace llvm {
|
||||
ELFSection::SHF_WRITE | ELFSection::SHF_ALLOC);
|
||||
}
|
||||
|
||||
/// ELFSym - This struct contains information about each symbol that is
|
||||
/// added to logical symbol table for the module. This is eventually
|
||||
/// turned into a real symbol table in the file.
|
||||
struct ELFSym {
|
||||
const GlobalValue *GV; // The global value this corresponds to.
|
||||
unsigned NameIdx; // Index in .strtab of name, once emitted.
|
||||
uint64_t Value;
|
||||
unsigned Size;
|
||||
unsigned char Info;
|
||||
unsigned char Other;
|
||||
unsigned short SectionIdx;
|
||||
|
||||
enum { STB_LOCAL = 0, STB_GLOBAL = 1, STB_WEAK = 2 };
|
||||
enum { STT_NOTYPE = 0, STT_OBJECT = 1, STT_FUNC = 2, STT_SECTION = 3,
|
||||
STT_FILE = 4 };
|
||||
ELFSym(const GlobalValue *gv) : GV(gv), Value(0), Size(0), Info(0),
|
||||
Other(0), SectionIdx(0) {}
|
||||
|
||||
void SetBind(unsigned X) {
|
||||
assert(X == (X & 0xF) && "Bind value out of range!");
|
||||
Info = (Info & 0x0F) | (X << 4);
|
||||
}
|
||||
void SetType(unsigned X) {
|
||||
assert(X == (X & 0xF) && "Type value out of range!");
|
||||
Info = (Info & 0xF0) | X;
|
||||
}
|
||||
};
|
||||
|
||||
/// SymbolTable - This is the list of symbols we have emitted to the file.
|
||||
/// This actually gets rearranged before emission to the file (to put the
|
||||
/// local symbols first in the list).
|
||||
@ -214,9 +144,9 @@ namespace llvm {
|
||||
// (e.g. the location of the section table). These members keep track of
|
||||
// the offset in ELFHeader of these various pieces to update and other
|
||||
// locations in the file.
|
||||
unsigned ELFHeader_e_shoff_Offset; // e_shoff in ELF header.
|
||||
unsigned ELFHeader_e_shstrndx_Offset; // e_shstrndx in ELF header.
|
||||
unsigned ELFHeader_e_shnum_Offset; // e_shnum in ELF header.
|
||||
unsigned ELFHdr_e_shoff_Offset; // e_shoff in ELF header.
|
||||
unsigned ELFHdr_e_shstrndx_Offset; // e_shstrndx in ELF header.
|
||||
unsigned ELFHdr_e_shnum_Offset; // e_shnum in ELF header.
|
||||
private:
|
||||
void EmitGlobal(GlobalVariable *GV);
|
||||
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "llvm/Support/Streams.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
@ -399,7 +398,7 @@ unsigned RALinScan::attemptTrivialCoalescing(LiveInterval &cur, unsigned Reg) {
|
||||
}
|
||||
|
||||
++NumCoalesce;
|
||||
return SrcReg;
|
||||
return PhysReg;
|
||||
}
|
||||
|
||||
return Reg;
|
||||
@ -543,13 +542,37 @@ void RALinScan::linearScan()
|
||||
// Ignore splited live intervals.
|
||||
if (!isPhys && vrm_->getPreSplitReg(cur.reg))
|
||||
continue;
|
||||
|
||||
// A register defined by an implicit_def can be liveout the def BB and livein
|
||||
// to a use BB. Add it to the livein set of the use BB's.
|
||||
if (!isPhys && cur.empty()) {
|
||||
if (MachineInstr *DefMI = mri_->getVRegDef(cur.reg)) {
|
||||
assert(DefMI->getOpcode() == TargetInstrInfo::IMPLICIT_DEF);
|
||||
MachineBasicBlock *DefMBB = DefMI->getParent();
|
||||
SmallPtrSet<MachineBasicBlock*, 4> Seen;
|
||||
Seen.insert(DefMBB);
|
||||
for (MachineRegisterInfo::reg_iterator ri = mri_->reg_begin(cur.reg),
|
||||
re = mri_->reg_end(); ri != re; ++ri) {
|
||||
MachineInstr *UseMI = &*ri;
|
||||
MachineBasicBlock *UseMBB = UseMI->getParent();
|
||||
if (Seen.insert(UseMBB)) {
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(Reg) &&
|
||||
"Adding a virtual register to livein set?");
|
||||
UseMBB->addLiveIn(Reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (LiveInterval::Ranges::const_iterator I = cur.begin(), E = cur.end();
|
||||
I != E; ++I) {
|
||||
const LiveRange &LR = *I;
|
||||
if (li_->findLiveInMBBs(LR.start, LR.end, LiveInMBBs)) {
|
||||
for (unsigned i = 0, e = LiveInMBBs.size(); i != e; ++i)
|
||||
if (LiveInMBBs[i] != EntryMBB)
|
||||
if (LiveInMBBs[i] != EntryMBB) {
|
||||
assert(TargetRegisterInfo::isPhysicalRegister(Reg) &&
|
||||
"Adding a virtual register to livein set?");
|
||||
LiveInMBBs[i]->addLiveIn(Reg);
|
||||
}
|
||||
LiveInMBBs.clear();
|
||||
}
|
||||
}
|
||||
@ -1192,7 +1215,6 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
||||
// The earliest start of a Spilled interval indicates up to where
|
||||
// in handled we need to roll back
|
||||
|
||||
unsigned earliestStart = cur->beginNumber();
|
||||
LiveInterval *earliestStartInterval = cur;
|
||||
|
||||
// Spill live intervals of virtual regs mapped to the physical register we
|
||||
@ -1206,19 +1228,10 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
||||
LiveInterval *sli = spillIs.back();
|
||||
spillIs.pop_back();
|
||||
DOUT << "\t\t\tspilling(a): " << *sli << '\n';
|
||||
earliestStart = std::min(earliestStart, sli->beginNumber());
|
||||
earliestStartInterval =
|
||||
(earliestStartInterval->beginNumber() < sli->beginNumber()) ?
|
||||
earliestStartInterval : sli;
|
||||
|
||||
if (earliestStartInterval->beginNumber()!=earliestStart) {
|
||||
epicFail |= true;
|
||||
std::cerr << "What the 1 - "
|
||||
<< "earliestStart = " << earliestStart
|
||||
<< "earliestStartInterval = " << earliestStartInterval->beginNumber()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
|
||||
std::vector<LiveInterval*> newIs;
|
||||
if (!NewSpillFramework) {
|
||||
newIs = li_->addIntervalsForSpills(*sli, spillIs, loopInfo, *vrm_);
|
||||
@ -1229,20 +1242,12 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur)
|
||||
std::copy(newIs.begin(), newIs.end(), std::back_inserter(added));
|
||||
spilled.insert(sli->reg);
|
||||
|
||||
if (earliestStartInterval->beginNumber()!=earliestStart) {
|
||||
epicFail |= true;
|
||||
std::cerr << "What the 2 - "
|
||||
<< "earliestStart = " << earliestStart
|
||||
<< "earliestStartInterval = " << earliestStartInterval->beginNumber()
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
if (epicFail) {
|
||||
//abort();
|
||||
}
|
||||
}
|
||||
|
||||
earliestStart = earliestStartInterval->beginNumber();
|
||||
unsigned earliestStart = earliestStartInterval->beginNumber();
|
||||
|
||||
DOUT << "\t\trolling back to: " << earliestStart << '\n';
|
||||
|
||||
|
@ -3626,30 +3626,29 @@ static SDNode *getBuildPairElt(SDNode *N, unsigned i) {
|
||||
SDValue DAGCombiner::CombineConsecutiveLoads(SDNode *N, MVT VT) {
|
||||
assert(N->getOpcode() == ISD::BUILD_PAIR);
|
||||
|
||||
SDNode *LD1 = getBuildPairElt(N, 0);
|
||||
if (!ISD::isNON_EXTLoad(LD1) || !LD1->hasOneUse())
|
||||
LoadSDNode *LD1 = dyn_cast<LoadSDNode>(getBuildPairElt(N, 0));
|
||||
LoadSDNode *LD2 = dyn_cast<LoadSDNode>(getBuildPairElt(N, 1));
|
||||
if (!LD1 || !LD2 || !ISD::isNON_EXTLoad(LD1) || !LD1->hasOneUse())
|
||||
return SDValue();
|
||||
MVT LD1VT = LD1->getValueType(0);
|
||||
SDNode *LD2 = getBuildPairElt(N, 1);
|
||||
const MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
|
||||
|
||||
if (ISD::isNON_EXTLoad(LD2) &&
|
||||
LD2->hasOneUse() &&
|
||||
// If both are volatile this would reduce the number of volatile loads.
|
||||
// If one is volatile it might be ok, but play conservative and bail out.
|
||||
!cast<LoadSDNode>(LD1)->isVolatile() &&
|
||||
!cast<LoadSDNode>(LD2)->isVolatile() &&
|
||||
!LD1->isVolatile() &&
|
||||
!LD2->isVolatile() &&
|
||||
TLI.isConsecutiveLoad(LD2, LD1, LD1VT.getSizeInBits()/8, 1, MFI)) {
|
||||
LoadSDNode *LD = cast<LoadSDNode>(LD1);
|
||||
unsigned Align = LD->getAlignment();
|
||||
unsigned Align = LD1->getAlignment();
|
||||
unsigned NewAlign = TLI.getTargetData()->
|
||||
getABITypeAlignment(VT.getTypeForMVT());
|
||||
|
||||
if (NewAlign <= Align &&
|
||||
(!LegalOperations || TLI.isOperationLegal(ISD::LOAD, VT)))
|
||||
return DAG.getLoad(VT, N->getDebugLoc(), LD->getChain(), LD->getBasePtr(),
|
||||
LD->getSrcValue(), LD->getSrcValueOffset(),
|
||||
false, Align);
|
||||
return DAG.getLoad(VT, N->getDebugLoc(), LD1->getChain(),
|
||||
LD1->getBasePtr(), LD1->getSrcValue(),
|
||||
LD1->getSrcValueOffset(), false, Align);
|
||||
}
|
||||
|
||||
return SDValue();
|
||||
@ -4019,6 +4018,9 @@ SDValue DAGCombiner::visitFMUL(SDNode *N) {
|
||||
// fold (fmul A, 0) -> 0
|
||||
if (UnsafeFPMath && N1CFP && N1CFP->getValueAPF().isZero())
|
||||
return N1;
|
||||
// fold (fmul A, 0) -> 0, vector edition.
|
||||
if (UnsafeFPMath && ISD::isBuildVectorAllZeros(N1.getNode()))
|
||||
return N1;
|
||||
// fold (fmul X, 2.0) -> (fadd X, X)
|
||||
if (N1CFP && N1CFP->isExactlyValue(+2.0))
|
||||
return DAG.getNode(ISD::FADD, N->getDebugLoc(), VT, N0, N0);
|
||||
|
@ -639,18 +639,18 @@ FastISel::FastEmitBranch(MachineBasicBlock *MSucc) {
|
||||
bool
|
||||
FastISel::SelectOperator(User *I, unsigned Opcode) {
|
||||
switch (Opcode) {
|
||||
case Instruction::Add: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FADD : ISD::ADD;
|
||||
return SelectBinaryOp(I, Opc);
|
||||
}
|
||||
case Instruction::Sub: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FSUB : ISD::SUB;
|
||||
return SelectBinaryOp(I, Opc);
|
||||
}
|
||||
case Instruction::Mul: {
|
||||
ISD::NodeType Opc = I->getType()->isFPOrFPVector() ? ISD::FMUL : ISD::MUL;
|
||||
return SelectBinaryOp(I, Opc);
|
||||
}
|
||||
case Instruction::Add:
|
||||
return SelectBinaryOp(I, ISD::ADD);
|
||||
case Instruction::FAdd:
|
||||
return SelectBinaryOp(I, ISD::FADD);
|
||||
case Instruction::Sub:
|
||||
return SelectBinaryOp(I, ISD::SUB);
|
||||
case Instruction::FSub:
|
||||
return SelectBinaryOp(I, ISD::FSUB);
|
||||
case Instruction::Mul:
|
||||
return SelectBinaryOp(I, ISD::MUL);
|
||||
case Instruction::FMul:
|
||||
return SelectBinaryOp(I, ISD::FMUL);
|
||||
case Instruction::SDiv:
|
||||
return SelectBinaryOp(I, ISD::SDIV);
|
||||
case Instruction::UDiv:
|
||||
|
@ -116,6 +116,8 @@ private:
|
||||
/// result.
|
||||
SDValue LegalizeOp(SDValue O);
|
||||
|
||||
SDValue OptimizeFloatStore(StoreSDNode *ST);
|
||||
|
||||
/// PerformInsertVectorEltInMemory - Some target cannot handle a variable
|
||||
/// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it
|
||||
/// is necessary to spill the vector being inserted into to memory, perform
|
||||
@ -165,6 +167,7 @@ private:
|
||||
SDValue ExpandBitCount(unsigned Opc, SDValue Op, DebugLoc dl);
|
||||
|
||||
SDValue ExpandExtractFromVectorThroughStack(SDValue Op);
|
||||
SDValue ExpandVectorBuildThroughStack(SDNode* Node);
|
||||
|
||||
void ExpandNode(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
||||
void PromoteNode(SDNode *Node, SmallVectorImpl<SDValue> &Results);
|
||||
@ -681,6 +684,59 @@ ExpandINSERT_VECTOR_ELT(SDValue Vec, SDValue Val, SDValue Idx, DebugLoc dl) {
|
||||
return PerformInsertVectorEltInMemory(Vec, Val, Idx, dl);
|
||||
}
|
||||
|
||||
SDValue SelectionDAGLegalize::OptimizeFloatStore(StoreSDNode* ST) {
|
||||
// Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr'
|
||||
// FIXME: We shouldn't do this for TargetConstantFP's.
|
||||
// FIXME: move this to the DAG Combiner! Note that we can't regress due
|
||||
// to phase ordering between legalized code and the dag combiner. This
|
||||
// probably means that we need to integrate dag combiner and legalizer
|
||||
// together.
|
||||
// We generally can't do this one for long doubles.
|
||||
SDValue Tmp1 = ST->getChain();
|
||||
SDValue Tmp2 = ST->getBasePtr();
|
||||
SDValue Tmp3;
|
||||
int SVOffset = ST->getSrcValueOffset();
|
||||
unsigned Alignment = ST->getAlignment();
|
||||
bool isVolatile = ST->isVolatile();
|
||||
DebugLoc dl = ST->getDebugLoc();
|
||||
if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(ST->getValue())) {
|
||||
if (CFP->getValueType(0) == MVT::f32 &&
|
||||
getTypeAction(MVT::i32) == Legal) {
|
||||
Tmp3 = DAG.getConstant(CFP->getValueAPF().
|
||||
bitcastToAPInt().zextOrTrunc(32),
|
||||
MVT::i32);
|
||||
return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
||||
SVOffset, isVolatile, Alignment);
|
||||
} else if (CFP->getValueType(0) == MVT::f64) {
|
||||
// If this target supports 64-bit registers, do a single 64-bit store.
|
||||
if (getTypeAction(MVT::i64) == Legal) {
|
||||
Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt().
|
||||
zextOrTrunc(64), MVT::i64);
|
||||
return DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
||||
SVOffset, isVolatile, Alignment);
|
||||
} else if (getTypeAction(MVT::i32) == Legal && !ST->isVolatile()) {
|
||||
// Otherwise, if the target supports 32-bit registers, use 2 32-bit
|
||||
// stores. If the target supports neither 32- nor 64-bits, this
|
||||
// xform is certainly not worth it.
|
||||
const APInt &IntVal =CFP->getValueAPF().bitcastToAPInt();
|
||||
SDValue Lo = DAG.getConstant(APInt(IntVal).trunc(32), MVT::i32);
|
||||
SDValue Hi = DAG.getConstant(IntVal.lshr(32).trunc(32), MVT::i32);
|
||||
if (TLI.isBigEndian()) std::swap(Lo, Hi);
|
||||
|
||||
Lo = DAG.getStore(Tmp1, dl, Lo, Tmp2, ST->getSrcValue(),
|
||||
SVOffset, isVolatile, Alignment);
|
||||
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
|
||||
DAG.getIntPtrConstant(4));
|
||||
Hi = DAG.getStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), SVOffset+4,
|
||||
isVolatile, MinAlign(Alignment, 4U));
|
||||
|
||||
return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi);
|
||||
}
|
||||
}
|
||||
}
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
/// LegalizeOp - We know that the specified value has a legal type, and
|
||||
/// that its operands are legal. Now ensure that the operation itself
|
||||
/// is legal, recursively ensuring that the operands' operations remain
|
||||
@ -1293,50 +1349,9 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
|
||||
bool isVolatile = ST->isVolatile();
|
||||
|
||||
if (!ST->isTruncatingStore()) {
|
||||
// Turn 'store float 1.0, Ptr' -> 'store int 0x12345678, Ptr'
|
||||
// FIXME: We shouldn't do this for TargetConstantFP's.
|
||||
// FIXME: move this to the DAG Combiner! Note that we can't regress due
|
||||
// to phase ordering between legalized code and the dag combiner. This
|
||||
// probably means that we need to integrate dag combiner and legalizer
|
||||
// together.
|
||||
// We generally can't do this one for long doubles.
|
||||
if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(ST->getValue())) {
|
||||
if (CFP->getValueType(0) == MVT::f32 &&
|
||||
getTypeAction(MVT::i32) == Legal) {
|
||||
Tmp3 = DAG.getConstant(CFP->getValueAPF().
|
||||
bitcastToAPInt().zextOrTrunc(32),
|
||||
MVT::i32);
|
||||
Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
||||
SVOffset, isVolatile, Alignment);
|
||||
break;
|
||||
} else if (CFP->getValueType(0) == MVT::f64) {
|
||||
// If this target supports 64-bit registers, do a single 64-bit store.
|
||||
if (getTypeAction(MVT::i64) == Legal) {
|
||||
Tmp3 = DAG.getConstant(CFP->getValueAPF().bitcastToAPInt().
|
||||
zextOrTrunc(64), MVT::i64);
|
||||
Result = DAG.getStore(Tmp1, dl, Tmp3, Tmp2, ST->getSrcValue(),
|
||||
SVOffset, isVolatile, Alignment);
|
||||
break;
|
||||
} else if (getTypeAction(MVT::i32) == Legal && !ST->isVolatile()) {
|
||||
// Otherwise, if the target supports 32-bit registers, use 2 32-bit
|
||||
// stores. If the target supports neither 32- nor 64-bits, this
|
||||
// xform is certainly not worth it.
|
||||
const APInt &IntVal =CFP->getValueAPF().bitcastToAPInt();
|
||||
SDValue Lo = DAG.getConstant(APInt(IntVal).trunc(32), MVT::i32);
|
||||
SDValue Hi = DAG.getConstant(IntVal.lshr(32).trunc(32), MVT::i32);
|
||||
if (TLI.isBigEndian()) std::swap(Lo, Hi);
|
||||
|
||||
Lo = DAG.getStore(Tmp1, dl, Lo, Tmp2, ST->getSrcValue(),
|
||||
SVOffset, isVolatile, Alignment);
|
||||
Tmp2 = DAG.getNode(ISD::ADD, dl, Tmp2.getValueType(), Tmp2,
|
||||
DAG.getIntPtrConstant(4));
|
||||
Hi = DAG.getStore(Tmp1, dl, Hi, Tmp2, ST->getSrcValue(), SVOffset+4,
|
||||
isVolatile, MinAlign(Alignment, 4U));
|
||||
|
||||
Result = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo, Hi);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (SDNode *OptStore = OptimizeFloatStore(ST).getNode()) {
|
||||
Result = SDValue(OptStore, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
{
|
||||
@ -1510,6 +1525,46 @@ SDValue SelectionDAGLegalize::ExpandExtractFromVectorThroughStack(SDValue Op) {
|
||||
return DAG.getLoad(Op.getValueType(), dl, Ch, StackPtr, NULL, 0);
|
||||
}
|
||||
|
||||
SDValue SelectionDAGLegalize::ExpandVectorBuildThroughStack(SDNode* Node) {
|
||||
// We can't handle this case efficiently. Allocate a sufficiently
|
||||
// aligned object on the stack, store each element into it, then load
|
||||
// the result as a vector.
|
||||
// Create the stack frame object.
|
||||
MVT VT = Node->getValueType(0);
|
||||
MVT OpVT = Node->getOperand(0).getValueType();
|
||||
DebugLoc dl = Node->getDebugLoc();
|
||||
SDValue FIPtr = DAG.CreateStackTemporary(VT);
|
||||
int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
|
||||
const Value *SV = PseudoSourceValue::getFixedStack(FI);
|
||||
|
||||
// Emit a store of each element to the stack slot.
|
||||
SmallVector<SDValue, 8> Stores;
|
||||
unsigned TypeByteSize = OpVT.getSizeInBits() / 8;
|
||||
// Store (in the right endianness) the elements to memory.
|
||||
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
|
||||
// Ignore undef elements.
|
||||
if (Node->getOperand(i).getOpcode() == ISD::UNDEF) continue;
|
||||
|
||||
unsigned Offset = TypeByteSize*i;
|
||||
|
||||
SDValue Idx = DAG.getConstant(Offset, FIPtr.getValueType());
|
||||
Idx = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, Idx);
|
||||
|
||||
Stores.push_back(DAG.getStore(DAG.getEntryNode(), dl, Node->getOperand(i),
|
||||
Idx, SV, Offset));
|
||||
}
|
||||
|
||||
SDValue StoreChain;
|
||||
if (!Stores.empty()) // Not all undef elements?
|
||||
StoreChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
||||
&Stores[0], Stores.size());
|
||||
else
|
||||
StoreChain = DAG.getEntryNode();
|
||||
|
||||
// Result is a load from the stack slot.
|
||||
return DAG.getLoad(VT, dl, StoreChain, FIPtr, SV, 0);
|
||||
}
|
||||
|
||||
SDValue SelectionDAGLegalize::ExpandFCOPYSIGN(SDNode* Node) {
|
||||
DebugLoc dl = Node->getDebugLoc();
|
||||
SDValue Tmp1 = Node->getOperand(0);
|
||||
@ -1853,40 +1908,8 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we can't handle this case efficiently. Allocate a sufficiently
|
||||
// aligned object on the stack, store each element into it, then load
|
||||
// the result as a vector.
|
||||
// Create the stack frame object.
|
||||
SDValue FIPtr = DAG.CreateStackTemporary(VT);
|
||||
int FI = cast<FrameIndexSDNode>(FIPtr.getNode())->getIndex();
|
||||
const Value *SV = PseudoSourceValue::getFixedStack(FI);
|
||||
|
||||
// Emit a store of each element to the stack slot.
|
||||
SmallVector<SDValue, 8> Stores;
|
||||
unsigned TypeByteSize = OpVT.getSizeInBits() / 8;
|
||||
// Store (in the right endianness) the elements to memory.
|
||||
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
|
||||
// Ignore undef elements.
|
||||
if (Node->getOperand(i).getOpcode() == ISD::UNDEF) continue;
|
||||
|
||||
unsigned Offset = TypeByteSize*i;
|
||||
|
||||
SDValue Idx = DAG.getConstant(Offset, FIPtr.getValueType());
|
||||
Idx = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, Idx);
|
||||
|
||||
Stores.push_back(DAG.getStore(DAG.getEntryNode(), dl, Node->getOperand(i),
|
||||
Idx, SV, Offset));
|
||||
}
|
||||
|
||||
SDValue StoreChain;
|
||||
if (!Stores.empty()) // Not all undef elements?
|
||||
StoreChain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
|
||||
&Stores[0], Stores.size());
|
||||
else
|
||||
StoreChain = DAG.getEntryNode();
|
||||
|
||||
// Result is a load from the stack slot.
|
||||
return DAG.getLoad(VT, dl, StoreChain, FIPtr, SV, 0);
|
||||
// Otherwise, we can't handle this case efficiently.
|
||||
return ExpandVectorBuildThroughStack(Node);
|
||||
}
|
||||
|
||||
// ExpandLibCall - Expand a node into a call to a libcall. If the result value
|
||||
@ -2437,23 +2460,7 @@ void SelectionDAGLegalize::ExpandNode(SDNode *Node,
|
||||
Results.push_back(ExpandExtractFromVectorThroughStack(SDValue(Node, 0)));
|
||||
break;
|
||||
case ISD::CONCAT_VECTORS: {
|
||||
// Use extract/insert/build vector for now. We might try to be
|
||||
// more clever later.
|
||||
SmallVector<SDValue, 8> Ops;
|
||||
unsigned NumOperands = Node->getNumOperands();
|
||||
for (unsigned i=0; i < NumOperands; ++i) {
|
||||
SDValue SubOp = Node->getOperand(i);
|
||||
MVT VVT = SubOp.getNode()->getValueType(0);
|
||||
MVT EltVT = VVT.getVectorElementType();
|
||||
unsigned NumSubElem = VVT.getVectorNumElements();
|
||||
for (unsigned j=0; j < NumSubElem; ++j) {
|
||||
Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, SubOp,
|
||||
DAG.getIntPtrConstant(j)));
|
||||
}
|
||||
}
|
||||
Tmp1 = DAG.getNode(ISD::BUILD_VECTOR, dl, Node->getValueType(0),
|
||||
&Ops[0], Ops.size());
|
||||
Results.push_back(Tmp1);
|
||||
Results.push_back(ExpandVectorBuildThroughStack(Node));
|
||||
break;
|
||||
}
|
||||
case ISD::SCALAR_TO_VECTOR:
|
||||
|
@ -356,13 +356,12 @@ SDValue DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) {
|
||||
unsigned NewOpc = N->getOpcode();
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
// If we're promoting a UINT to a larger size, check to see if the new node
|
||||
// will be legal. If it isn't, check to see if FP_TO_SINT is legal, since
|
||||
// we can use that instead. This allows us to generate better code for
|
||||
// FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not
|
||||
// legal, such as PowerPC.
|
||||
// If we're promoting a UINT to a larger size and the larger FP_TO_UINT is
|
||||
// not Legal, check to see if we can use FP_TO_SINT instead. (If both UINT
|
||||
// and SINT conversions are Custom, there is no way to tell which is preferable.
|
||||
// We choose SINT because that's the right thing on PPC.)
|
||||
if (N->getOpcode() == ISD::FP_TO_UINT &&
|
||||
!TLI.isOperationLegalOrCustom(ISD::FP_TO_UINT, NVT) &&
|
||||
!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) &&
|
||||
TLI.isOperationLegalOrCustom(ISD::FP_TO_SINT, NVT))
|
||||
NewOpc = ISD::FP_TO_SINT;
|
||||
|
||||
@ -1747,7 +1746,9 @@ void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N,
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
|
||||
if (VT == MVT::i32)
|
||||
if (VT == MVT::i16)
|
||||
LC = RTLIB::SDIV_I16;
|
||||
else if (VT == MVT::i32)
|
||||
LC = RTLIB::SDIV_I32;
|
||||
else if (VT == MVT::i64)
|
||||
LC = RTLIB::SDIV_I64;
|
||||
@ -1909,7 +1910,9 @@ void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N,
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
|
||||
if (VT == MVT::i32)
|
||||
if (VT == MVT::i16)
|
||||
LC = RTLIB::SREM_I16;
|
||||
else if (VT == MVT::i32)
|
||||
LC = RTLIB::SREM_I32;
|
||||
else if (VT == MVT::i64)
|
||||
LC = RTLIB::SREM_I64;
|
||||
@ -1938,7 +1941,9 @@ void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N,
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
|
||||
if (VT == MVT::i32)
|
||||
if (VT == MVT::i16)
|
||||
LC = RTLIB::UDIV_I16;
|
||||
else if (VT == MVT::i32)
|
||||
LC = RTLIB::UDIV_I32;
|
||||
else if (VT == MVT::i64)
|
||||
LC = RTLIB::UDIV_I64;
|
||||
@ -1956,7 +1961,9 @@ void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N,
|
||||
DebugLoc dl = N->getDebugLoc();
|
||||
|
||||
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
|
||||
if (VT == MVT::i32)
|
||||
if (VT == MVT::i16)
|
||||
LC = RTLIB::UREM_I16;
|
||||
else if (VT == MVT::i32)
|
||||
LC = RTLIB::UREM_I32;
|
||||
else if (VT == MVT::i64)
|
||||
LC = RTLIB::UREM_I64;
|
||||
|
@ -129,6 +129,7 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
|
||||
if (!HasVectorValue)
|
||||
return TranslateLegalizeResults(Op, Result);
|
||||
|
||||
MVT QueryType;
|
||||
switch (Op.getOpcode()) {
|
||||
default:
|
||||
return TranslateLegalizeResults(Op, Result);
|
||||
@ -162,8 +163,6 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
|
||||
case ISD::ANY_EXTEND:
|
||||
case ISD::TRUNCATE:
|
||||
case ISD::SIGN_EXTEND:
|
||||
case ISD::SINT_TO_FP:
|
||||
case ISD::UINT_TO_FP:
|
||||
case ISD::FP_TO_SINT:
|
||||
case ISD::FP_TO_UINT:
|
||||
case ISD::FNEG:
|
||||
@ -183,10 +182,15 @@ SDValue VectorLegalizer::LegalizeOp(SDValue Op) {
|
||||
case ISD::FRINT:
|
||||
case ISD::FNEARBYINT:
|
||||
case ISD::FFLOOR:
|
||||
QueryType = Node->getValueType(0);
|
||||
break;
|
||||
case ISD::SINT_TO_FP:
|
||||
case ISD::UINT_TO_FP:
|
||||
QueryType = Node->getOperand(0).getValueType();
|
||||
break;
|
||||
}
|
||||
|
||||
switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
|
||||
switch (TLI.getOperationAction(Node->getOpcode(), QueryType)) {
|
||||
case TargetLowering::Promote:
|
||||
// "Promote" the operation by bitcasting
|
||||
Result = PromoteVectorOp(Op);
|
||||
|
@ -154,7 +154,7 @@ bool ISD::isBuildVectorAllZeros(const SDNode *N) {
|
||||
// Do not accept an all-undef vector.
|
||||
if (i == e) return false;
|
||||
|
||||
// Do not accept build_vectors that aren't all constants or which have non-~0
|
||||
// Do not accept build_vectors that aren't all constants or which have non-0
|
||||
// elements.
|
||||
SDValue Zero = N->getOperand(i);
|
||||
if (isa<ConstantSDNode>(Zero)) {
|
||||
@ -166,7 +166,7 @@ bool ISD::isBuildVectorAllZeros(const SDNode *N) {
|
||||
} else
|
||||
return false;
|
||||
|
||||
// Okay, we have at least one ~0 value, check to see if the rest match or are
|
||||
// Okay, we have at least one 0 value, check to see if the rest match or are
|
||||
// undefs.
|
||||
for (++i; i != e; ++i)
|
||||
if (N->getOperand(i) != Zero &&
|
||||
@ -2807,16 +2807,19 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT,
|
||||
case ISD::ADDC:
|
||||
case ISD::ADDE:
|
||||
case ISD::SUB:
|
||||
case ISD::FADD:
|
||||
case ISD::FSUB:
|
||||
case ISD::FMUL:
|
||||
case ISD::FDIV:
|
||||
case ISD::FREM:
|
||||
case ISD::UDIV:
|
||||
case ISD::SDIV:
|
||||
case ISD::UREM:
|
||||
case ISD::SREM:
|
||||
return N2; // fold op(arg1, undef) -> undef
|
||||
case ISD::FADD:
|
||||
case ISD::FSUB:
|
||||
case ISD::FMUL:
|
||||
case ISD::FDIV:
|
||||
case ISD::FREM:
|
||||
if (UnsafeFPMath)
|
||||
return N2;
|
||||
break;
|
||||
case ISD::MUL:
|
||||
case ISD::AND:
|
||||
case ISD::SRL:
|
||||
@ -3059,7 +3062,7 @@ bool MeetsMaxMemopRequirement(std::vector<MVT> &MemOps,
|
||||
isSrcStr = isMemSrcFromString(Src, Str);
|
||||
bool isSrcConst = isa<ConstantSDNode>(Src);
|
||||
bool AllowUnalign = TLI.allowsUnalignedMemoryAccesses();
|
||||
MVT VT = TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr);
|
||||
MVT VT = TLI.getOptimalMemOpType(Size, Align, isSrcConst, isSrcStr, DAG);
|
||||
if (VT != MVT::iAny) {
|
||||
unsigned NewAlign = (unsigned)
|
||||
TLI.getTargetData()->getABITypeAlignment(VT.getTypeForMVT());
|
||||
|
@ -842,20 +842,6 @@ void SelectionDAGLowering::visit(unsigned Opcode, User &I) {
|
||||
}
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitAdd(User &I) {
|
||||
if (I.getType()->isFPOrFPVector())
|
||||
visitBinary(I, ISD::FADD);
|
||||
else
|
||||
visitBinary(I, ISD::ADD);
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitMul(User &I) {
|
||||
if (I.getType()->isFPOrFPVector())
|
||||
visitBinary(I, ISD::FMUL);
|
||||
else
|
||||
visitBinary(I, ISD::MUL);
|
||||
}
|
||||
|
||||
SDValue SelectionDAGLowering::getValue(const Value *V) {
|
||||
SDValue &N = NodeMap[V];
|
||||
if (N.getNode()) return N;
|
||||
@ -2161,37 +2147,33 @@ void SelectionDAGLowering::visitSwitch(SwitchInst &SI) {
|
||||
}
|
||||
|
||||
|
||||
void SelectionDAGLowering::visitSub(User &I) {
|
||||
void SelectionDAGLowering::visitFSub(User &I) {
|
||||
// -0.0 - X --> fneg
|
||||
const Type *Ty = I.getType();
|
||||
if (isa<VectorType>(Ty)) {
|
||||
if (ConstantVector *CV = dyn_cast<ConstantVector>(I.getOperand(0))) {
|
||||
const VectorType *DestTy = cast<VectorType>(I.getType());
|
||||
const Type *ElTy = DestTy->getElementType();
|
||||
if (ElTy->isFloatingPoint()) {
|
||||
unsigned VL = DestTy->getNumElements();
|
||||
std::vector<Constant*> NZ(VL, ConstantFP::getNegativeZero(ElTy));
|
||||
Constant *CNZ = ConstantVector::get(&NZ[0], NZ.size());
|
||||
if (CV == CNZ) {
|
||||
SDValue Op2 = getValue(I.getOperand(1));
|
||||
setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(),
|
||||
Op2.getValueType(), Op2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Ty->isFloatingPoint()) {
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0)))
|
||||
if (CFP->isExactlyValue(ConstantFP::getNegativeZero(Ty)->getValueAPF())) {
|
||||
unsigned VL = DestTy->getNumElements();
|
||||
std::vector<Constant*> NZ(VL, ConstantFP::getNegativeZero(ElTy));
|
||||
Constant *CNZ = ConstantVector::get(&NZ[0], NZ.size());
|
||||
if (CV == CNZ) {
|
||||
SDValue Op2 = getValue(I.getOperand(1));
|
||||
setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(),
|
||||
Op2.getValueType(), Op2));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(I.getOperand(0)))
|
||||
if (CFP->isExactlyValue(ConstantFP::getNegativeZero(Ty)->getValueAPF())) {
|
||||
SDValue Op2 = getValue(I.getOperand(1));
|
||||
setValue(&I, DAG.getNode(ISD::FNEG, getCurDebugLoc(),
|
||||
Op2.getValueType(), Op2));
|
||||
return;
|
||||
}
|
||||
|
||||
visitBinary(I, Ty->isFPOrFPVector() ? ISD::FSUB : ISD::SUB);
|
||||
visitBinary(I, ISD::FSUB);
|
||||
}
|
||||
|
||||
void SelectionDAGLowering::visitBinary(User &I, unsigned OpCode) {
|
||||
|
@ -469,9 +469,12 @@ private:
|
||||
|
||||
void visitBinary(User &I, unsigned OpCode);
|
||||
void visitShift(User &I, unsigned Opcode);
|
||||
void visitAdd(User &I);
|
||||
void visitSub(User &I);
|
||||
void visitMul(User &I);
|
||||
void visitAdd(User &I) { visitBinary(I, ISD::ADD); }
|
||||
void visitFAdd(User &I) { visitBinary(I, ISD::FADD); }
|
||||
void visitSub(User &I) { visitBinary(I, ISD::SUB); }
|
||||
void visitFSub(User &I);
|
||||
void visitMul(User &I) { visitBinary(I, ISD::MUL); }
|
||||
void visitFMul(User &I) { visitBinary(I, ISD::FMUL); }
|
||||
void visitURem(User &I) { visitBinary(I, ISD::UREM); }
|
||||
void visitSRem(User &I) { visitBinary(I, ISD::SREM); }
|
||||
void visitFRem(User &I) { visitBinary(I, ISD::FREM); }
|
||||
|
@ -2070,13 +2070,13 @@ bool TargetLowering::isGAPlusOffset(SDNode *N, GlobalValue* &GA,
|
||||
}
|
||||
|
||||
|
||||
/// isConsecutiveLoad - Return true if LD (which must be a LoadSDNode) is
|
||||
/// loading 'Bytes' bytes from a location that is 'Dist' units away from the
|
||||
/// location that the 'Base' load is loading from.
|
||||
bool TargetLowering::isConsecutiveLoad(SDNode *LD, SDNode *Base,
|
||||
unsigned Bytes, int Dist,
|
||||
/// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a
|
||||
/// location that is 'Dist' units away from the location that the 'Base' load
|
||||
/// is loading from.
|
||||
bool TargetLowering::isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base,
|
||||
unsigned Bytes, int Dist,
|
||||
const MachineFrameInfo *MFI) const {
|
||||
if (LD->getOperand(0).getNode() != Base->getOperand(0).getNode())
|
||||
if (LD->getChain() != Base->getChain())
|
||||
return false;
|
||||
MVT VT = LD->getValueType(0);
|
||||
if (VT.getSizeInBits() / 8 != Bytes)
|
||||
@ -2094,6 +2094,11 @@ bool TargetLowering::isConsecutiveLoad(SDNode *LD, SDNode *Base,
|
||||
if (FS != BFS || FS != (int)Bytes) return false;
|
||||
return MFI->getObjectOffset(FI) == (MFI->getObjectOffset(BFI) + Dist*Bytes);
|
||||
}
|
||||
if (Loc.getOpcode() == ISD::ADD && Loc.getOperand(0) == BaseLoc) {
|
||||
ConstantSDNode *V = dyn_cast<ConstantSDNode>(Loc.getOperand(1));
|
||||
if (V && (V->getSExtValue() == Dist*Bytes))
|
||||
return true;
|
||||
}
|
||||
|
||||
GlobalValue *GV1 = NULL;
|
||||
GlobalValue *GV2 = NULL;
|
||||
|
@ -33,99 +33,21 @@ STATISTIC(NumSUnfold , "Number of stores unfolded");
|
||||
STATISTIC(NumModRefUnfold, "Number of modref unfolded");
|
||||
|
||||
namespace {
|
||||
enum RewriterName { simple, local, trivial };
|
||||
enum RewriterName { local, trivial };
|
||||
}
|
||||
|
||||
static cl::opt<RewriterName>
|
||||
RewriterOpt("rewriter",
|
||||
cl::desc("Rewriter to use: (default: local)"),
|
||||
cl::Prefix,
|
||||
cl::values(clEnumVal(simple, "simple rewriter"),
|
||||
clEnumVal(local, "local rewriter"),
|
||||
cl::values(clEnumVal(local, "local rewriter"),
|
||||
clEnumVal(trivial, "trivial rewriter"),
|
||||
clEnumValEnd),
|
||||
cl::init(local));
|
||||
|
||||
VirtRegRewriter::~VirtRegRewriter() {}
|
||||
|
||||
|
||||
// ****************************** //
|
||||
// Simple Spiller Implementation //
|
||||
// ****************************** //
|
||||
|
||||
struct VISIBILITY_HIDDEN SimpleRewriter : public VirtRegRewriter {
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM,
|
||||
LiveIntervals* LIs) {
|
||||
DOUT << "********** REWRITE MACHINE CODE **********\n";
|
||||
DOUT << "********** Function: " << MF.getFunction()->getName() << '\n';
|
||||
const TargetMachine &TM = MF.getTarget();
|
||||
const TargetInstrInfo &TII = *TM.getInstrInfo();
|
||||
const TargetRegisterInfo &TRI = *TM.getRegisterInfo();
|
||||
|
||||
|
||||
// LoadedRegs - Keep track of which vregs are loaded, so that we only load
|
||||
// each vreg once (in the case where a spilled vreg is used by multiple
|
||||
// operands). This is always smaller than the number of operands to the
|
||||
// current machine instr, so it should be small.
|
||||
std::vector<unsigned> LoadedRegs;
|
||||
|
||||
for (MachineFunction::iterator MBBI = MF.begin(), E = MF.end();
|
||||
MBBI != E; ++MBBI) {
|
||||
DOUT << MBBI->getBasicBlock()->getName() << ":\n";
|
||||
MachineBasicBlock &MBB = *MBBI;
|
||||
for (MachineBasicBlock::iterator MII = MBB.begin(), E = MBB.end();
|
||||
MII != E; ++MII) {
|
||||
MachineInstr &MI = *MII;
|
||||
for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
|
||||
MachineOperand &MO = MI.getOperand(i);
|
||||
if (MO.isReg() && MO.getReg()) {
|
||||
if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
|
||||
unsigned VirtReg = MO.getReg();
|
||||
unsigned SubIdx = MO.getSubReg();
|
||||
unsigned PhysReg = VRM.getPhys(VirtReg);
|
||||
unsigned RReg = SubIdx ? TRI.getSubReg(PhysReg, SubIdx) : PhysReg;
|
||||
if (!VRM.isAssignedReg(VirtReg)) {
|
||||
int StackSlot = VRM.getStackSlot(VirtReg);
|
||||
const TargetRegisterClass* RC =
|
||||
MF.getRegInfo().getRegClass(VirtReg);
|
||||
|
||||
if (MO.isUse() &&
|
||||
std::find(LoadedRegs.begin(), LoadedRegs.end(), VirtReg)
|
||||
== LoadedRegs.end()) {
|
||||
TII.loadRegFromStackSlot(MBB, &MI, PhysReg, StackSlot, RC);
|
||||
MachineInstr *LoadMI = prior(MII);
|
||||
VRM.addSpillSlotUse(StackSlot, LoadMI);
|
||||
LoadedRegs.push_back(VirtReg);
|
||||
++NumLoads;
|
||||
DOUT << '\t' << *LoadMI;
|
||||
}
|
||||
|
||||
if (MO.isDef()) {
|
||||
TII.storeRegToStackSlot(MBB, next(MII), PhysReg, true,
|
||||
StackSlot, RC);
|
||||
MachineInstr *StoreMI = next(MII);
|
||||
VRM.addSpillSlotUse(StackSlot, StoreMI);
|
||||
++NumStores;
|
||||
}
|
||||
}
|
||||
MF.getRegInfo().setPhysRegUsed(RReg);
|
||||
MI.getOperand(i).setReg(RReg);
|
||||
MI.getOperand(i).setSubReg(0);
|
||||
} else {
|
||||
MF.getRegInfo().setPhysRegUsed(MO.getReg());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DOUT << '\t' << MI;
|
||||
LoadedRegs.clear();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// This class is intended for use with the new spilling framework only. It
|
||||
/// rewrites vreg def/uses to use the assigned preg, but does not insert any
|
||||
@ -2231,8 +2153,6 @@ llvm::VirtRegRewriter* llvm::createVirtRegRewriter() {
|
||||
default: assert(0 && "Unreachable!");
|
||||
case local:
|
||||
return new LocalRewriter();
|
||||
case simple:
|
||||
return new SimpleRewriter();
|
||||
case trivial:
|
||||
return new TrivialRewriter();
|
||||
}
|
||||
|
@ -573,8 +573,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
||||
return GV;
|
||||
}
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::URem:
|
||||
@ -605,11 +608,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
||||
case Type::FloatTyID:
|
||||
switch (CE->getOpcode()) {
|
||||
default: assert(0 && "Invalid float opcode"); abort();
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
GV.FloatVal = LHS.FloatVal + RHS.FloatVal; break;
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
GV.FloatVal = LHS.FloatVal - RHS.FloatVal; break;
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
GV.FloatVal = LHS.FloatVal * RHS.FloatVal; break;
|
||||
case Instruction::FDiv:
|
||||
GV.FloatVal = LHS.FloatVal / RHS.FloatVal; break;
|
||||
@ -620,11 +623,11 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
||||
case Type::DoubleTyID:
|
||||
switch (CE->getOpcode()) {
|
||||
default: assert(0 && "Invalid double opcode"); abort();
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
GV.DoubleVal = LHS.DoubleVal + RHS.DoubleVal; break;
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
GV.DoubleVal = LHS.DoubleVal - RHS.DoubleVal; break;
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
GV.DoubleVal = LHS.DoubleVal * RHS.DoubleVal; break;
|
||||
case Instruction::FDiv:
|
||||
GV.DoubleVal = LHS.DoubleVal / RHS.DoubleVal; break;
|
||||
@ -638,15 +641,15 @@ GenericValue ExecutionEngine::getConstantValue(const Constant *C) {
|
||||
APFloat apfLHS = APFloat(LHS.IntVal);
|
||||
switch (CE->getOpcode()) {
|
||||
default: assert(0 && "Invalid long double opcode"); abort();
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
apfLHS.add(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
|
||||
GV.IntVal = apfLHS.bitcastToAPInt();
|
||||
break;
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
apfLHS.subtract(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
|
||||
GV.IntVal = apfLHS.bitcastToAPInt();
|
||||
break;
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
apfLHS.multiply(APFloat(RHS.IntVal), APFloat::rmNearestTiesToEven);
|
||||
GV.IntVal = apfLHS.bitcastToAPInt();
|
||||
break;
|
||||
|
@ -64,45 +64,35 @@ void Interpreter::initializeExecutionEngine() {
|
||||
Dest.TY##Val = Src1.TY##Val OP Src2.TY##Val; \
|
||||
break
|
||||
|
||||
#define IMPLEMENT_INTEGER_BINOP1(OP, TY) \
|
||||
case Type::IntegerTyID: { \
|
||||
Dest.IntVal = Src1.IntVal OP Src2.IntVal; \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
static void executeAddInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
static void executeFAddInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_INTEGER_BINOP1(+, Ty);
|
||||
IMPLEMENT_BINARY_OPERATOR(+, Float);
|
||||
IMPLEMENT_BINARY_OPERATOR(+, Double);
|
||||
default:
|
||||
cerr << "Unhandled type for Add instruction: " << *Ty << "\n";
|
||||
cerr << "Unhandled type for FAdd instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void executeSubInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
static void executeFSubInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_INTEGER_BINOP1(-, Ty);
|
||||
IMPLEMENT_BINARY_OPERATOR(-, Float);
|
||||
IMPLEMENT_BINARY_OPERATOR(-, Double);
|
||||
default:
|
||||
cerr << "Unhandled type for Sub instruction: " << *Ty << "\n";
|
||||
cerr << "Unhandled type for FSub instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
static void executeMulInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
static void executeFMulInst(GenericValue &Dest, GenericValue Src1,
|
||||
GenericValue Src2, const Type *Ty) {
|
||||
switch (Ty->getTypeID()) {
|
||||
IMPLEMENT_INTEGER_BINOP1(*, Ty);
|
||||
IMPLEMENT_BINARY_OPERATOR(*, Float);
|
||||
IMPLEMENT_BINARY_OPERATOR(*, Double);
|
||||
default:
|
||||
cerr << "Unhandled type for Mul instruction: " << *Ty << "\n";
|
||||
cerr << "Unhandled type for FMul instruction: " << *Ty << "\n";
|
||||
abort();
|
||||
}
|
||||
}
|
||||
@ -550,11 +540,14 @@ void Interpreter::visitBinaryOperator(BinaryOperator &I) {
|
||||
GenericValue R; // Result
|
||||
|
||||
switch (I.getOpcode()) {
|
||||
case Instruction::Add: executeAddInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::Sub: executeSubInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::Mul: executeMulInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::FDiv: executeFDivInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::FRem: executeFRemInst (R, Src1, Src2, Ty); break;
|
||||
case Instruction::Add: R.IntVal = Src1.IntVal + Src2.IntVal; break;
|
||||
case Instruction::Sub: R.IntVal = Src1.IntVal - Src2.IntVal; break;
|
||||
case Instruction::Mul: R.IntVal = Src1.IntVal * Src2.IntVal; break;
|
||||
case Instruction::FAdd: executeFAddInst(R, Src1, Src2, Ty); break;
|
||||
case Instruction::FSub: executeFSubInst(R, Src1, Src2, Ty); break;
|
||||
case Instruction::FMul: executeFMulInst(R, Src1, Src2, Ty); break;
|
||||
case Instruction::FDiv: executeFDivInst(R, Src1, Src2, Ty); break;
|
||||
case Instruction::FRem: executeFRemInst(R, Src1, Src2, Ty); break;
|
||||
case Instruction::UDiv: R.IntVal = Src1.IntVal.udiv(Src2.IntVal); break;
|
||||
case Instruction::SDiv: R.IntVal = Src1.IntVal.sdiv(Src2.IntVal); break;
|
||||
case Instruction::URem: R.IntVal = Src1.IntVal.urem(Src2.IntVal); break;
|
||||
@ -1258,18 +1251,21 @@ GenericValue Interpreter::getConstantExprValue (ConstantExpr *CE,
|
||||
GenericValue Dest;
|
||||
const Type * Ty = CE->getOperand(0)->getType();
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::Add: executeAddInst (Dest, Op0, Op1, Ty); break;
|
||||
case Instruction::Sub: executeSubInst (Dest, Op0, Op1, Ty); break;
|
||||
case Instruction::Mul: executeMulInst (Dest, Op0, Op1, Ty); break;
|
||||
case Instruction::Add: Dest.IntVal = Op0.IntVal + Op1.IntVal; break;
|
||||
case Instruction::Sub: Dest.IntVal = Op0.IntVal - Op1.IntVal; break;
|
||||
case Instruction::Mul: Dest.IntVal = Op0.IntVal * Op1.IntVal; break;
|
||||
case Instruction::FAdd: executeFAddInst(Dest, Op0, Op1, Ty); break;
|
||||
case Instruction::FSub: executeFSubInst(Dest, Op0, Op1, Ty); break;
|
||||
case Instruction::FMul: executeFMulInst(Dest, Op0, Op1, Ty); break;
|
||||
case Instruction::FDiv: executeFDivInst(Dest, Op0, Op1, Ty); break;
|
||||
case Instruction::FRem: executeFRemInst(Dest, Op0, Op1, Ty); break;
|
||||
case Instruction::SDiv: Dest.IntVal = Op0.IntVal.sdiv(Op1.IntVal); break;
|
||||
case Instruction::UDiv: Dest.IntVal = Op0.IntVal.udiv(Op1.IntVal); break;
|
||||
case Instruction::URem: Dest.IntVal = Op0.IntVal.urem(Op1.IntVal); break;
|
||||
case Instruction::SRem: Dest.IntVal = Op0.IntVal.srem(Op1.IntVal); break;
|
||||
case Instruction::And: Dest.IntVal = Op0.IntVal.And(Op1.IntVal); break;
|
||||
case Instruction::Or: Dest.IntVal = Op0.IntVal.Or(Op1.IntVal); break;
|
||||
case Instruction::Xor: Dest.IntVal = Op0.IntVal.Xor(Op1.IntVal); break;
|
||||
case Instruction::And: Dest.IntVal = Op0.IntVal & Op1.IntVal; break;
|
||||
case Instruction::Or: Dest.IntVal = Op0.IntVal | Op1.IntVal; break;
|
||||
case Instruction::Xor: Dest.IntVal = Op0.IntVal ^ Op1.IntVal; break;
|
||||
case Instruction::Shl:
|
||||
Dest.IntVal = Op0.IntVal.shl(Op1.IntVal.getZExtValue());
|
||||
break;
|
||||
|
@ -551,7 +551,7 @@ namespace {
|
||||
|
||||
// When outputting a function stub in the context of some other function, we
|
||||
// save BufferBegin/BufferEnd/CurBufferPtr here.
|
||||
unsigned char *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr;
|
||||
uint8_t *SavedBufferBegin, *SavedBufferEnd, *SavedCurBufferPtr;
|
||||
|
||||
/// Relocations - These are the relocations that the function needs, as
|
||||
/// emitted.
|
||||
@ -891,8 +891,11 @@ unsigned JITEmitter::addSizeOfGlobalsInConstantVal(const Constant *C,
|
||||
break;
|
||||
}
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::URem:
|
||||
@ -1056,11 +1059,11 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
|
||||
|
||||
// FnStart is the start of the text, not the start of the constant pool and
|
||||
// other per-function data.
|
||||
unsigned char *FnStart =
|
||||
(unsigned char *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction());
|
||||
uint8_t *FnStart =
|
||||
(uint8_t *)TheJIT->getPointerToGlobalIfAvailable(F.getFunction());
|
||||
|
||||
// FnEnd is the end of the function's machine code.
|
||||
unsigned char *FnEnd = CurBufferPtr;
|
||||
uint8_t *FnEnd = CurBufferPtr;
|
||||
|
||||
if (!Relocations.empty()) {
|
||||
CurFn = F.getFunction();
|
||||
@ -1183,7 +1186,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
|
||||
} else {
|
||||
DOUT << "JIT: Binary code:\n";
|
||||
DOUT << std::hex;
|
||||
unsigned char* q = FnStart;
|
||||
uint8_t* q = FnStart;
|
||||
for (int i = 0; q < FnEnd; q += 4, ++i) {
|
||||
if (i == 4)
|
||||
i = 0;
|
||||
@ -1221,7 +1224,7 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
|
||||
BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
|
||||
ActualSize);
|
||||
BufferEnd = BufferBegin+ActualSize;
|
||||
unsigned char* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd);
|
||||
uint8_t* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd);
|
||||
MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr,
|
||||
FrameRegister);
|
||||
BufferBegin = SavedBufferBegin;
|
||||
@ -1416,7 +1419,7 @@ void JITEmitter::startGVStub(const GlobalValue* GV, void *Buffer,
|
||||
SavedBufferEnd = BufferEnd;
|
||||
SavedCurBufferPtr = CurBufferPtr;
|
||||
|
||||
BufferBegin = CurBufferPtr = (unsigned char *)Buffer;
|
||||
BufferBegin = CurBufferPtr = (uint8_t *)Buffer;
|
||||
BufferEnd = BufferBegin+StubSize+1;
|
||||
}
|
||||
|
||||
|
@ -257,9 +257,9 @@ namespace {
|
||||
// When emitting code into a memory block, this is the block.
|
||||
MemoryRangeHeader *CurBlock;
|
||||
|
||||
unsigned char *CurStubPtr, *StubBase;
|
||||
unsigned char *GOTBase; // Target Specific reserved memory
|
||||
void *DlsymTable; // Stub external symbol information
|
||||
uint8_t *CurStubPtr, *StubBase;
|
||||
uint8_t *GOTBase; // Target Specific reserved memory
|
||||
void *DlsymTable; // Stub external symbol information
|
||||
|
||||
// Centralize memory block allocation.
|
||||
sys::MemoryBlock getNewMemoryBlock(unsigned size);
|
||||
@ -273,12 +273,12 @@ namespace {
|
||||
void AllocateGOT();
|
||||
void SetDlsymTable(void *);
|
||||
|
||||
unsigned char *allocateStub(const GlobalValue* F, unsigned StubSize,
|
||||
unsigned Alignment);
|
||||
uint8_t *allocateStub(const GlobalValue* F, unsigned StubSize,
|
||||
unsigned Alignment);
|
||||
|
||||
/// startFunctionBody - When a function starts, allocate a block of free
|
||||
/// executable memory, returning a pointer to it and its actual size.
|
||||
unsigned char *startFunctionBody(const Function *F, uintptr_t &ActualSize) {
|
||||
uint8_t *startFunctionBody(const Function *F, uintptr_t &ActualSize) {
|
||||
|
||||
FreeRangeHeader* candidateBlock = FreeMemoryList;
|
||||
FreeRangeHeader* head = FreeMemoryList;
|
||||
@ -301,18 +301,18 @@ namespace {
|
||||
// Allocate the entire memory block.
|
||||
FreeMemoryList = candidateBlock->AllocateBlock();
|
||||
ActualSize = CurBlock->BlockSize-sizeof(MemoryRangeHeader);
|
||||
return (unsigned char *)(CurBlock+1);
|
||||
return (uint8_t *)(CurBlock+1);
|
||||
}
|
||||
|
||||
/// endFunctionBody - The function F is now allocated, and takes the memory
|
||||
/// in the range [FunctionStart,FunctionEnd).
|
||||
void endFunctionBody(const Function *F, unsigned char *FunctionStart,
|
||||
unsigned char *FunctionEnd) {
|
||||
void endFunctionBody(const Function *F, uint8_t *FunctionStart,
|
||||
uint8_t *FunctionEnd) {
|
||||
assert(FunctionEnd > FunctionStart);
|
||||
assert(FunctionStart == (unsigned char *)(CurBlock+1) &&
|
||||
assert(FunctionStart == (uint8_t *)(CurBlock+1) &&
|
||||
"Mismatched function start/end!");
|
||||
|
||||
uintptr_t BlockSize = FunctionEnd - (unsigned char *)CurBlock;
|
||||
uintptr_t BlockSize = FunctionEnd - (uint8_t *)CurBlock;
|
||||
FunctionBlocks[F] = CurBlock;
|
||||
|
||||
// Release the memory at the end of this block that isn't needed.
|
||||
@ -320,17 +320,17 @@ namespace {
|
||||
}
|
||||
|
||||
/// allocateSpace - Allocate a memory block of the given size.
|
||||
unsigned char *allocateSpace(intptr_t Size, unsigned Alignment) {
|
||||
uint8_t *allocateSpace(intptr_t Size, unsigned Alignment) {
|
||||
CurBlock = FreeMemoryList;
|
||||
FreeMemoryList = FreeMemoryList->AllocateBlock();
|
||||
|
||||
unsigned char *result = (unsigned char *)CurBlock+1;
|
||||
uint8_t *result = (uint8_t *)CurBlock+1;
|
||||
|
||||
if (Alignment == 0) Alignment = 1;
|
||||
result = (unsigned char*)(((intptr_t)result+Alignment-1) &
|
||||
result = (uint8_t*)(((intptr_t)result+Alignment-1) &
|
||||
~(intptr_t)(Alignment-1));
|
||||
|
||||
uintptr_t BlockSize = result + Size - (unsigned char *)CurBlock;
|
||||
uintptr_t BlockSize = result + Size - (uint8_t *)CurBlock;
|
||||
FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
|
||||
|
||||
return result;
|
||||
@ -338,28 +338,26 @@ namespace {
|
||||
|
||||
/// startExceptionTable - Use startFunctionBody to allocate memory for the
|
||||
/// function's exception table.
|
||||
unsigned char* startExceptionTable(const Function* F,
|
||||
uintptr_t &ActualSize) {
|
||||
uint8_t* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
|
||||
return startFunctionBody(F, ActualSize);
|
||||
}
|
||||
|
||||
/// endExceptionTable - The exception table of F is now allocated,
|
||||
/// and takes the memory in the range [TableStart,TableEnd).
|
||||
void endExceptionTable(const Function *F, unsigned char *TableStart,
|
||||
unsigned char *TableEnd,
|
||||
unsigned char* FrameRegister) {
|
||||
void endExceptionTable(const Function *F, uint8_t *TableStart,
|
||||
uint8_t *TableEnd, uint8_t* FrameRegister) {
|
||||
assert(TableEnd > TableStart);
|
||||
assert(TableStart == (unsigned char *)(CurBlock+1) &&
|
||||
assert(TableStart == (uint8_t *)(CurBlock+1) &&
|
||||
"Mismatched table start/end!");
|
||||
|
||||
uintptr_t BlockSize = TableEnd - (unsigned char *)CurBlock;
|
||||
uintptr_t BlockSize = TableEnd - (uint8_t *)CurBlock;
|
||||
TableBlocks[F] = CurBlock;
|
||||
|
||||
// Release the memory at the end of this block that isn't needed.
|
||||
FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
|
||||
}
|
||||
|
||||
unsigned char *getGOTBase() const {
|
||||
uint8_t *getGOTBase() const {
|
||||
return GOTBase;
|
||||
}
|
||||
|
||||
@ -433,7 +431,7 @@ DefaultJITMemoryManager::DefaultJITMemoryManager() {
|
||||
sys::MemoryBlock MemBlock = getNewMemoryBlock(16 << 20);
|
||||
#endif
|
||||
|
||||
unsigned char *MemBase = static_cast<unsigned char*>(MemBlock.base());
|
||||
uint8_t *MemBase = static_cast<uint8_t*>(MemBlock.base());
|
||||
|
||||
// Allocate stubs backwards from the base, allocate functions forward
|
||||
// from the base.
|
||||
@ -492,7 +490,7 @@ DefaultJITMemoryManager::DefaultJITMemoryManager() {
|
||||
|
||||
void DefaultJITMemoryManager::AllocateGOT() {
|
||||
assert(GOTBase == 0 && "Cannot allocate the got multiple times");
|
||||
GOTBase = new unsigned char[sizeof(void*) * 8192];
|
||||
GOTBase = new uint8_t[sizeof(void*) * 8192];
|
||||
HasGOT = true;
|
||||
}
|
||||
|
||||
@ -508,12 +506,12 @@ DefaultJITMemoryManager::~DefaultJITMemoryManager() {
|
||||
Blocks.clear();
|
||||
}
|
||||
|
||||
unsigned char *DefaultJITMemoryManager::allocateStub(const GlobalValue* F,
|
||||
uint8_t *DefaultJITMemoryManager::allocateStub(const GlobalValue* F,
|
||||
unsigned StubSize,
|
||||
unsigned Alignment) {
|
||||
CurStubPtr -= StubSize;
|
||||
CurStubPtr = (unsigned char*)(((intptr_t)CurStubPtr) &
|
||||
~(intptr_t)(Alignment-1));
|
||||
CurStubPtr = (uint8_t*)(((intptr_t)CurStubPtr) &
|
||||
~(intptr_t)(Alignment-1));
|
||||
if (CurStubPtr < StubBase) {
|
||||
// FIXME: allocate a new block
|
||||
fprintf(stderr, "JIT ran out of memory for function stubs!\n");
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/System/Program.h"
|
||||
#include "llvm/System/Process.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Config/config.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
@ -301,6 +302,35 @@ uint64_t raw_fd_ostream::seek(uint64_t off) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
raw_ostream &raw_fd_ostream::changeColor(enum Colors colors, bool bold,
|
||||
bool bg) {
|
||||
if (sys::Process::ColorNeedsFlush())
|
||||
flush();
|
||||
const char *colorcode =
|
||||
(colors == SAVEDCOLOR) ? sys::Process::OutputBold(bg)
|
||||
: sys::Process::OutputColor(colors, bold, bg);
|
||||
if (colorcode) {
|
||||
unsigned len = strlen(colorcode);
|
||||
write(colorcode, len);
|
||||
// don't account colors towards output characters
|
||||
pos -= len;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
raw_ostream &raw_fd_ostream::resetColor() {
|
||||
if (sys::Process::ColorNeedsFlush())
|
||||
flush();
|
||||
const char *colorcode = sys::Process::ResetColor();
|
||||
if (colorcode) {
|
||||
unsigned len = strlen(colorcode);
|
||||
write(colorcode, len);
|
||||
// don't account colors towards output characters
|
||||
pos -= len;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// raw_stdout/err_ostream
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -235,3 +235,62 @@ unsigned Process::StandardErrColumns() {
|
||||
|
||||
return getColumns(2);
|
||||
}
|
||||
|
||||
static bool terminalHasColors() {
|
||||
if (const char *term = std::getenv("TERM")) {
|
||||
// Most modern terminals support ANSI escape sequences for colors.
|
||||
// We could check terminfo, or have a list of known terms that support
|
||||
// colors, but that would be overkill.
|
||||
// The user can always ask for no colors by setting TERM to dumb, or
|
||||
// using a commandline flag.
|
||||
return strcmp(term, "dumb") != 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Process::StandardOutHasColors() {
|
||||
if (!StandardOutIsDisplayed())
|
||||
return false;
|
||||
return terminalHasColors();
|
||||
}
|
||||
|
||||
bool Process::StandardErrHasColors() {
|
||||
if (!StandardErrIsDisplayed())
|
||||
return false;
|
||||
return terminalHasColors();
|
||||
}
|
||||
|
||||
bool Process::ColorNeedsFlush() {
|
||||
// No, we use ANSI escape sequences.
|
||||
return false;
|
||||
}
|
||||
|
||||
#define COLOR(FGBG, CODE, BOLD) "\033[0;" BOLD FGBG CODE "m"
|
||||
|
||||
#define ALLCOLORS(FGBG,BOLD) {\
|
||||
COLOR(FGBG, "0", BOLD),\
|
||||
COLOR(FGBG, "1", BOLD),\
|
||||
COLOR(FGBG, "2", BOLD),\
|
||||
COLOR(FGBG, "3", BOLD),\
|
||||
COLOR(FGBG, "4", BOLD),\
|
||||
COLOR(FGBG, "5", BOLD),\
|
||||
COLOR(FGBG, "6", BOLD),\
|
||||
COLOR(FGBG, "7", BOLD)\
|
||||
}
|
||||
|
||||
static const char* colorcodes[2][2][8] = {
|
||||
{ ALLCOLORS("3",""), ALLCOLORS("3","1;") },
|
||||
{ ALLCOLORS("4",""), ALLCOLORS("4","1;") }
|
||||
};
|
||||
|
||||
const char *Process::OutputColor(char code, bool bold, bool bg) {
|
||||
return colorcodes[bg?1:0][bold?1:0][code&7];
|
||||
}
|
||||
|
||||
const char *Process::OutputBold(bool bg) {
|
||||
return "\033[1m";
|
||||
}
|
||||
|
||||
const char *Process::ResetColor() {
|
||||
return "\033[0m";
|
||||
}
|
||||
|
@ -147,4 +147,71 @@ unsigned Process::StandardErrColumns() {
|
||||
return Columns;
|
||||
}
|
||||
|
||||
// It always has colors.
|
||||
bool Process::StandardErrHasColors() {
|
||||
return StandardErrIsDisplayed();
|
||||
}
|
||||
|
||||
bool Process::StandardOutHasColors() {
|
||||
return StandardOutIsDisplayed();
|
||||
}
|
||||
|
||||
namespace {
|
||||
class DefaultColors
|
||||
{
|
||||
private:
|
||||
WORD defaultColor;
|
||||
public:
|
||||
DefaultColors()
|
||||
:defaultColor(GetCurrentColor()) {}
|
||||
static unsigned GetCurrentColor() {
|
||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
|
||||
return csbi.wAttributes;
|
||||
return 0;
|
||||
}
|
||||
WORD operator()() const { return defaultColor; }
|
||||
};
|
||||
|
||||
DefaultColors defaultColors;
|
||||
}
|
||||
|
||||
bool Process::ColorNeedsFlush() {
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *Process::OutputBold(bool bg) {
|
||||
WORD colors = DefaultColors::GetCurrentColor();
|
||||
if (bg)
|
||||
colors |= BACKGROUND_INTENSITY;
|
||||
else
|
||||
colors |= FOREGROUND_INTENSITY;
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *Process::OutputColor(char code, bool bold, bool bg) {
|
||||
WORD colors;
|
||||
if (bg) {
|
||||
colors = ((code&1) ? BACKGROUND_RED : 0) |
|
||||
((code&2) ? BACKGROUND_GREEN : 0 ) |
|
||||
((code&4) ? BACKGROUND_BLUE : 0);
|
||||
if (bold)
|
||||
colors |= BACKGROUND_INTENSITY;
|
||||
} else {
|
||||
colors = ((code&1) ? FOREGROUND_RED : 0) |
|
||||
((code&2) ? FOREGROUND_GREEN : 0 ) |
|
||||
((code&4) ? FOREGROUND_BLUE : 0);
|
||||
if (bold)
|
||||
colors |= FOREGROUND_INTENSITY;
|
||||
}
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), colors);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *Process::ResetColor() {
|
||||
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), defaultColors());
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include "llvm/Type.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <ostream>
|
||||
using namespace llvm;
|
||||
|
||||
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||
|
@ -64,11 +64,15 @@ namespace {
|
||||
typedef SmallVector<MemOpQueueEntry,8> MemOpQueue;
|
||||
typedef MemOpQueue::iterator MemOpQueueIter;
|
||||
|
||||
SmallVector<MachineBasicBlock::iterator, 4>
|
||||
MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
|
||||
int Opcode, unsigned Size,
|
||||
ARMCC::CondCodes Pred, unsigned PredReg,
|
||||
unsigned Scratch, MemOpQueue &MemOps);
|
||||
bool MergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
int Offset, unsigned Base, bool BaseKill, int Opcode,
|
||||
ARMCC::CondCodes Pred, unsigned PredReg, unsigned Scratch,
|
||||
DebugLoc dl, SmallVector<std::pair<unsigned, bool>, 8> &Regs);
|
||||
void MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex, unsigned Base,
|
||||
int Opcode, unsigned Size,
|
||||
ARMCC::CondCodes Pred, unsigned PredReg,
|
||||
unsigned Scratch, MemOpQueue &MemOps,
|
||||
SmallVector<MachineBasicBlock::iterator, 4> &Merges);
|
||||
|
||||
void AdvanceRS(MachineBasicBlock &MBB, MemOpQueue &MemOps);
|
||||
bool LoadStoreMultipleOpti(MachineBasicBlock &MBB);
|
||||
@ -108,16 +112,16 @@ static int getLoadStoreMultipleOpcode(int Opcode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// mergeOps - Create and insert a LDM or STM with Base as base register and
|
||||
/// MergeOps - Create and insert a LDM or STM with Base as base register and
|
||||
/// registers in Regs as the register operands that would be loaded / stored.
|
||||
/// It returns true if the transformation is done.
|
||||
static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
int Offset, unsigned Base, bool BaseKill, int Opcode,
|
||||
ARMCC::CondCodes Pred, unsigned PredReg, unsigned Scratch,
|
||||
SmallVector<std::pair<unsigned, bool>, 8> &Regs,
|
||||
const TargetInstrInfo *TII) {
|
||||
// FIXME would it be better to take a DL from one of the loads arbitrarily?
|
||||
DebugLoc dl = DebugLoc::getUnknownLoc();
|
||||
bool
|
||||
ARMLoadStoreOpt::MergeOps(MachineBasicBlock &MBB,
|
||||
MachineBasicBlock::iterator MBBI,
|
||||
int Offset, unsigned Base, bool BaseKill,
|
||||
int Opcode, ARMCC::CondCodes Pred,
|
||||
unsigned PredReg, unsigned Scratch, DebugLoc dl,
|
||||
SmallVector<std::pair<unsigned, bool>, 8> &Regs) {
|
||||
// Only a single register to load / store. Don't bother.
|
||||
unsigned NumRegs = Regs.size();
|
||||
if (NumRegs <= 1)
|
||||
@ -185,20 +189,21 @@ static bool mergeOps(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
|
||||
/// MergeLDR_STR - Merge a number of load / store instructions into one or more
|
||||
/// load / store multiple instructions.
|
||||
SmallVector<MachineBasicBlock::iterator, 4>
|
||||
void
|
||||
ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
||||
unsigned Base, int Opcode, unsigned Size,
|
||||
ARMCC::CondCodes Pred, unsigned PredReg,
|
||||
unsigned Scratch, MemOpQueue &MemOps) {
|
||||
SmallVector<MachineBasicBlock::iterator, 4> Merges;
|
||||
unsigned Base, int Opcode, unsigned Size,
|
||||
ARMCC::CondCodes Pred, unsigned PredReg,
|
||||
unsigned Scratch, MemOpQueue &MemOps,
|
||||
SmallVector<MachineBasicBlock::iterator, 4> &Merges) {
|
||||
bool isAM4 = Opcode == ARM::LDR || Opcode == ARM::STR;
|
||||
int Offset = MemOps[SIndex].Offset;
|
||||
int SOffset = Offset;
|
||||
unsigned Pos = MemOps[SIndex].Position;
|
||||
MachineBasicBlock::iterator Loc = MemOps[SIndex].MBBI;
|
||||
unsigned PReg = MemOps[SIndex].MBBI->getOperand(0).getReg();
|
||||
DebugLoc dl = Loc->getDebugLoc();
|
||||
unsigned PReg = Loc->getOperand(0).getReg();
|
||||
unsigned PRegNum = ARMRegisterInfo::getRegisterNumbering(PReg);
|
||||
bool isKill = MemOps[SIndex].MBBI->getOperand(0).isKill();
|
||||
bool isKill = Loc->getOperand(0).isKill();
|
||||
|
||||
SmallVector<std::pair<unsigned,bool>, 8> Regs;
|
||||
Regs.push_back(std::make_pair(PReg, isKill));
|
||||
@ -216,18 +221,17 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
||||
PRegNum = RegNum;
|
||||
} else {
|
||||
// Can't merge this in. Try merge the earlier ones first.
|
||||
if (mergeOps(MBB, ++Loc, SOffset, Base, false, Opcode, Pred, PredReg,
|
||||
Scratch, Regs, TII)) {
|
||||
if (MergeOps(MBB, ++Loc, SOffset, Base, false, Opcode, Pred, PredReg,
|
||||
Scratch, dl, Regs)) {
|
||||
Merges.push_back(prior(Loc));
|
||||
for (unsigned j = SIndex; j < i; ++j) {
|
||||
MBB.erase(MemOps[j].MBBI);
|
||||
MemOps[j].Merged = true;
|
||||
}
|
||||
}
|
||||
SmallVector<MachineBasicBlock::iterator, 4> Merges2 =
|
||||
MergeLDR_STR(MBB, i, Base, Opcode, Size, Pred, PredReg, Scratch,MemOps);
|
||||
Merges.append(Merges2.begin(), Merges2.end());
|
||||
return Merges;
|
||||
MergeLDR_STR(MBB, i, Base, Opcode, Size, Pred, PredReg, Scratch,
|
||||
MemOps, Merges);
|
||||
return;
|
||||
}
|
||||
|
||||
if (MemOps[i].Position > Pos) {
|
||||
@ -237,8 +241,8 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
||||
}
|
||||
|
||||
bool BaseKill = Loc->findRegisterUseOperandIdx(Base, true) != -1;
|
||||
if (mergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode, Pred, PredReg,
|
||||
Scratch, Regs, TII)) {
|
||||
if (MergeOps(MBB, ++Loc, SOffset, Base, BaseKill, Opcode, Pred, PredReg,
|
||||
Scratch, dl, Regs)) {
|
||||
Merges.push_back(prior(Loc));
|
||||
for (unsigned i = SIndex, e = MemOps.size(); i != e; ++i) {
|
||||
MBB.erase(MemOps[i].MBBI);
|
||||
@ -246,7 +250,7 @@ ARMLoadStoreOpt::MergeLDR_STR(MachineBasicBlock &MBB, unsigned SIndex,
|
||||
}
|
||||
}
|
||||
|
||||
return Merges;
|
||||
return;
|
||||
}
|
||||
|
||||
/// getInstrPredicate - If instruction is predicated, returns its predicate
|
||||
@ -530,7 +534,7 @@ static bool mergeBaseUpdateLoadStore(MachineBasicBlock &MBB,
|
||||
if (isAM2)
|
||||
// STR_PRE, STR_POST;
|
||||
BuildMI(MBB, MBBI, dl, TII->get(NewOpc), Base)
|
||||
.addReg(MO.getReg(), getKillRegState(BaseKill))
|
||||
.addReg(MO.getReg(), getKillRegState(MO.isKill()))
|
||||
.addReg(Base).addReg(0).addImm(Offset).addImm(Pred).addReg(PredReg);
|
||||
else
|
||||
// FSTMS, FSTMD
|
||||
@ -590,6 +594,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
||||
ARMCC::CondCodes CurrPred = ARMCC::AL;
|
||||
unsigned CurrPredReg = 0;
|
||||
unsigned Position = 0;
|
||||
SmallVector<MachineBasicBlock::iterator,4> Merges;
|
||||
|
||||
RS->enterBasicBlock(&MBB);
|
||||
MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
|
||||
@ -689,16 +694,16 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
||||
RS->forward(prior(MBBI));
|
||||
|
||||
// Merge ops.
|
||||
SmallVector<MachineBasicBlock::iterator,4> MBBII =
|
||||
MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize,
|
||||
CurrPred, CurrPredReg, Scratch, MemOps);
|
||||
Merges.clear();
|
||||
MergeLDR_STR(MBB, 0, CurrBase, CurrOpc, CurrSize,
|
||||
CurrPred, CurrPredReg, Scratch, MemOps, Merges);
|
||||
|
||||
// Try folding preceeding/trailing base inc/dec into the generated
|
||||
// LDM/STM ops.
|
||||
for (unsigned i = 0, e = MBBII.size(); i < e; ++i)
|
||||
if (mergeBaseUpdateLSMultiple(MBB, MBBII[i], Advance, MBBI))
|
||||
for (unsigned i = 0, e = Merges.size(); i < e; ++i)
|
||||
if (mergeBaseUpdateLSMultiple(MBB, Merges[i], Advance, MBBI))
|
||||
++NumMerges;
|
||||
NumMerges += MBBII.size();
|
||||
NumMerges += Merges.size();
|
||||
|
||||
// Try folding preceeding/trailing base inc/dec into those load/store
|
||||
// that were not merged to form LDM/STM ops.
|
||||
@ -709,6 +714,13 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) {
|
||||
|
||||
// RS may be pointing to an instruction that's deleted.
|
||||
RS->skipTo(prior(MBBI));
|
||||
} else if (NumMemOps == 1) {
|
||||
// Try folding preceeding/trailing base inc/dec into the single
|
||||
// load/store.
|
||||
if (mergeBaseUpdateLoadStore(MBB, MemOps[0].MBBI, TII, Advance, MBBI)) {
|
||||
++NumMerges;
|
||||
RS->forward(prior(MBBI));
|
||||
}
|
||||
}
|
||||
|
||||
CurrBase = 0;
|
||||
|
@ -100,7 +100,7 @@ public:
|
||||
GPRCS1Frames(0), GPRCS2Frames(0), DPRCSFrames(0),
|
||||
JumpTableUId(0), ConstPoolEntryUId(0) {}
|
||||
|
||||
ARMFunctionInfo(MachineFunction &MF) :
|
||||
explicit ARMFunctionInfo(MachineFunction &MF) :
|
||||
isThumb(MF.getTarget().getSubtarget<ARMSubtarget>().isThumb()),
|
||||
Align(isThumb ? 1U : 2U),
|
||||
VarArgsRegSaveSize(0), HasStackFrame(false),
|
||||
|
@ -103,28 +103,28 @@ def GPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6,
|
||||
let MethodBodies = [{
|
||||
// FP is R11, R9 is available.
|
||||
static const unsigned ARM_GPR_AO_1[] = {
|
||||
ARM::R3, ARM::R2, ARM::R1, ARM::R0,
|
||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
||||
ARM::R12,ARM::LR,
|
||||
ARM::R4, ARM::R5, ARM::R6, ARM::R7,
|
||||
ARM::R8, ARM::R9, ARM::R10,
|
||||
ARM::R11 };
|
||||
// FP is R11, R9 is not available.
|
||||
static const unsigned ARM_GPR_AO_2[] = {
|
||||
ARM::R3, ARM::R2, ARM::R1, ARM::R0,
|
||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
||||
ARM::R12,ARM::LR,
|
||||
ARM::R4, ARM::R5, ARM::R6, ARM::R7,
|
||||
ARM::R8, ARM::R10,
|
||||
ARM::R11 };
|
||||
// FP is R7, R9 is available.
|
||||
static const unsigned ARM_GPR_AO_3[] = {
|
||||
ARM::R3, ARM::R2, ARM::R1, ARM::R0,
|
||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
||||
ARM::R12,ARM::LR,
|
||||
ARM::R4, ARM::R5, ARM::R6,
|
||||
ARM::R8, ARM::R9, ARM::R10,ARM::R11,
|
||||
ARM::R7 };
|
||||
// FP is R7, R9 is not available.
|
||||
static const unsigned ARM_GPR_AO_4[] = {
|
||||
ARM::R3, ARM::R2, ARM::R1, ARM::R0,
|
||||
ARM::R0, ARM::R1, ARM::R2, ARM::R3,
|
||||
ARM::R12,ARM::LR,
|
||||
ARM::R4, ARM::R5, ARM::R6,
|
||||
ARM::R8, ARM::R10,ARM::R11,
|
||||
@ -186,7 +186,7 @@ def tGPR : RegisterClass<"ARM", [i32], 32, [R0, R1, R2, R3, R4, R5, R6, R7]> {
|
||||
// scavenging.
|
||||
let MethodBodies = [{
|
||||
static const unsigned THUMB_tGPR_AO[] = {
|
||||
ARM::R2, ARM::R1, ARM::R0,
|
||||
ARM::R0, ARM::R1, ARM::R2,
|
||||
ARM::R4, ARM::R5, ARM::R6, ARM::R7 };
|
||||
|
||||
// FP is R7, only low registers available.
|
||||
|
@ -33,8 +33,8 @@ class AlphaMachineFunctionInfo : public MachineFunctionInfo {
|
||||
public:
|
||||
AlphaMachineFunctionInfo() : GlobalBaseReg(0), GlobalRetAddr(0) {}
|
||||
|
||||
AlphaMachineFunctionInfo(MachineFunction &MF) : GlobalBaseReg(0),
|
||||
GlobalRetAddr(0) {}
|
||||
explicit AlphaMachineFunctionInfo(MachineFunction &MF) : GlobalBaseReg(0),
|
||||
GlobalRetAddr(0) {}
|
||||
|
||||
unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
|
||||
void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
|
||||
|
@ -1000,8 +1000,11 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
|
||||
Out << ')';
|
||||
return;
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::FDiv:
|
||||
@ -1020,9 +1023,12 @@ void CWriter::printConstant(Constant *CPV, bool Static) {
|
||||
bool NeedsClosingParens = printConstExprCast(CE, Static);
|
||||
printConstantWithCast(CE->getOperand(0), CE->getOpcode());
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::Add: Out << " + "; break;
|
||||
case Instruction::Sub: Out << " - "; break;
|
||||
case Instruction::Mul: Out << " * "; break;
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd: Out << " + "; break;
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub: Out << " - "; break;
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul: Out << " * "; break;
|
||||
case Instruction::URem:
|
||||
case Instruction::SRem:
|
||||
case Instruction::FRem: Out << " % "; break;
|
||||
@ -1322,8 +1328,6 @@ bool CWriter::printConstExprCast(const ConstantExpr* CE, bool Static) {
|
||||
case Instruction::Mul:
|
||||
// We need to cast integer arithmetic so that it is always performed
|
||||
// as unsigned, to avoid undefined behavior on overflow.
|
||||
if (!Ty->isIntOrIntVector()) break;
|
||||
// FALL THROUGH
|
||||
case Instruction::LShr:
|
||||
case Instruction::URem:
|
||||
case Instruction::UDiv: NeedsExplicitCast = true; break;
|
||||
@ -1387,8 +1391,6 @@ void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) {
|
||||
case Instruction::Mul:
|
||||
// We need to cast integer arithmetic so that it is always performed
|
||||
// as unsigned, to avoid undefined behavior on overflow.
|
||||
if (!OpTy->isIntOrIntVector()) break;
|
||||
// FALL THROUGH
|
||||
case Instruction::LShr:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::URem:
|
||||
@ -1505,8 +1507,6 @@ bool CWriter::writeInstructionCast(const Instruction &I) {
|
||||
case Instruction::Mul:
|
||||
// We need to cast integer arithmetic so that it is always performed
|
||||
// as unsigned, to avoid undefined behavior on overflow.
|
||||
if (!Ty->isIntOrIntVector()) break;
|
||||
// FALL THROUGH
|
||||
case Instruction::LShr:
|
||||
case Instruction::URem:
|
||||
case Instruction::UDiv:
|
||||
@ -1552,8 +1552,6 @@ void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) {
|
||||
case Instruction::Mul:
|
||||
// We need to cast integer arithmetic so that it is always performed
|
||||
// as unsigned, to avoid undefined behavior on overflow.
|
||||
if (!OpTy->isIntOrIntVector()) break;
|
||||
// FALL THROUGH
|
||||
case Instruction::LShr:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::URem: // Cast to unsigned first
|
||||
@ -2606,6 +2604,10 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
Out << "-(";
|
||||
writeOperand(BinaryOperator::getNegArgument(cast<BinaryOperator>(&I)));
|
||||
Out << ")";
|
||||
} else if (BinaryOperator::isFNeg(&I)) {
|
||||
Out << "-(";
|
||||
writeOperand(BinaryOperator::getFNegArgument(cast<BinaryOperator>(&I)));
|
||||
Out << ")";
|
||||
} else if (I.getOpcode() == Instruction::FRem) {
|
||||
// Output a call to fmod/fmodf instead of emitting a%b
|
||||
if (I.getType() == Type::FloatTy)
|
||||
@ -2630,9 +2632,12 @@ void CWriter::visitBinaryOperator(Instruction &I) {
|
||||
writeOperandWithCast(I.getOperand(0), I.getOpcode());
|
||||
|
||||
switch (I.getOpcode()) {
|
||||
case Instruction::Add: Out << " + "; break;
|
||||
case Instruction::Sub: Out << " - "; break;
|
||||
case Instruction::Mul: Out << " * "; break;
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd: Out << " + "; break;
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub: Out << " - "; break;
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul: Out << " * "; break;
|
||||
case Instruction::URem:
|
||||
case Instruction::SRem:
|
||||
case Instruction::FRem: Out << " % "; break;
|
||||
|
@ -865,8 +865,11 @@ namespace {
|
||||
Out << "Constant* " << constName << " = ConstantExpr::";
|
||||
switch (CE->getOpcode()) {
|
||||
case Instruction::Add: Out << "getAdd("; break;
|
||||
case Instruction::FAdd: Out << "getFAdd("; break;
|
||||
case Instruction::Sub: Out << "getSub("; break;
|
||||
case Instruction::FSub: Out << "getFSub("; break;
|
||||
case Instruction::Mul: Out << "getMul("; break;
|
||||
case Instruction::FMul: Out << "getFMul("; break;
|
||||
case Instruction::UDiv: Out << "getUDiv("; break;
|
||||
case Instruction::SDiv: Out << "getSDiv("; break;
|
||||
case Instruction::FDiv: Out << "getFDiv("; break;
|
||||
@ -1159,8 +1162,11 @@ namespace {
|
||||
break;
|
||||
}
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
case Instruction::UDiv:
|
||||
case Instruction::SDiv:
|
||||
case Instruction::FDiv:
|
||||
@ -1176,8 +1182,11 @@ namespace {
|
||||
Out << "BinaryOperator* " << iName << " = BinaryOperator::Create(";
|
||||
switch (I->getOpcode()) {
|
||||
case Instruction::Add: Out << "Instruction::Add"; break;
|
||||
case Instruction::FAdd: Out << "Instruction::FAdd"; break;
|
||||
case Instruction::Sub: Out << "Instruction::Sub"; break;
|
||||
case Instruction::FSub: Out << "Instruction::FSub"; break;
|
||||
case Instruction::Mul: Out << "Instruction::Mul"; break;
|
||||
case Instruction::FMul: Out << "Instruction::FMul"; break;
|
||||
case Instruction::UDiv:Out << "Instruction::UDiv"; break;
|
||||
case Instruction::SDiv:Out << "Instruction::SDiv"; break;
|
||||
case Instruction::FDiv:Out << "Instruction::FDiv"; break;
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
// by this machinefunction? (used to compute the appropriate
|
||||
// entry in the 'alloc' instruction at the top of the
|
||||
// machinefunction)
|
||||
IA64FunctionInfo(MachineFunction& MF) { outRegsUsed=0; };
|
||||
explicit IA64FunctionInfo(MachineFunction& MF) { outRegsUsed=0; };
|
||||
|
||||
};
|
||||
|
||||
|
@ -1060,12 +1060,15 @@ void MSILWriter::printInstruction(const Instruction* Inst) {
|
||||
break;
|
||||
// Binary
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
printBinaryInstruction("add",Left,Right);
|
||||
break;
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
printBinaryInstruction("sub",Left,Right);
|
||||
break;
|
||||
case Instruction::Mul:
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
printBinaryInstruction("mul",Left,Right);
|
||||
break;
|
||||
case Instruction::UDiv:
|
||||
@ -1322,12 +1325,15 @@ void MSILWriter::printConstantExpr(const ConstantExpr* CE) {
|
||||
printSelectInstruction(CE->getOperand(0),CE->getOperand(1),CE->getOperand(2));
|
||||
break;
|
||||
case Instruction::Add:
|
||||
case Instruction::FAdd:
|
||||
printBinaryInstruction("add",left,right);
|
||||
break;
|
||||
case Instruction::Sub:
|
||||
case Instruction::FSub:
|
||||
printBinaryInstruction("sub",left,right);
|
||||
break;
|
||||
case Instruction::Mul:
|
||||
case Instruction::FMul:
|
||||
printBinaryInstruction("mul",left,right);
|
||||
break;
|
||||
case Instruction::UDiv:
|
||||
|
@ -28,7 +28,8 @@ class MSP430MachineFunctionInfo : public MachineFunctionInfo {
|
||||
public:
|
||||
MSP430MachineFunctionInfo() : CalleeSavedFrameSize(0) {}
|
||||
|
||||
MSP430MachineFunctionInfo(MachineFunction &MF) : CalleeSavedFrameSize(0) {}
|
||||
explicit MSP430MachineFunctionInfo(MachineFunction &MF)
|
||||
: CalleeSavedFrameSize(0) {}
|
||||
|
||||
unsigned getCalleeSavedFrameSize() const { return CalleeSavedFrameSize; }
|
||||
void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; }
|
||||
|
@ -46,6 +46,16 @@ static const char *getIntrinsicName(unsigned opcode) {
|
||||
case PIC16ISD::MUL_I8: Basename = "mul.i8"; break;
|
||||
case RTLIB::MUL_I16: Basename = "mul.i16"; break;
|
||||
case RTLIB::MUL_I32: Basename = "mul.i32"; break;
|
||||
|
||||
case RTLIB::SDIV_I16: Basename = "sdiv.i16"; break;
|
||||
case RTLIB::SDIV_I32: Basename = "sdiv.i32"; break;
|
||||
case RTLIB::UDIV_I16: Basename = "udiv.i16"; break;
|
||||
case RTLIB::UDIV_I32: Basename = "udiv.i32"; break;
|
||||
|
||||
case RTLIB::SREM_I16: Basename = "srem.i16"; break;
|
||||
case RTLIB::SREM_I32: Basename = "srem.i32"; break;
|
||||
case RTLIB::UREM_I16: Basename = "urem.i16"; break;
|
||||
case RTLIB::UREM_I32: Basename = "urem.i32"; break;
|
||||
}
|
||||
|
||||
std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
|
||||
@ -90,6 +100,20 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
|
||||
setLibcallName(RTLIB::MUL_I16, getIntrinsicName(RTLIB::MUL_I16));
|
||||
setLibcallName(RTLIB::MUL_I32, getIntrinsicName(RTLIB::MUL_I32));
|
||||
|
||||
// Signed division lib call names
|
||||
setLibcallName(RTLIB::SDIV_I16, getIntrinsicName(RTLIB::SDIV_I16));
|
||||
setLibcallName(RTLIB::SDIV_I32, getIntrinsicName(RTLIB::SDIV_I32));
|
||||
// Unsigned division lib call names
|
||||
setLibcallName(RTLIB::UDIV_I16, getIntrinsicName(RTLIB::UDIV_I16));
|
||||
setLibcallName(RTLIB::UDIV_I32, getIntrinsicName(RTLIB::UDIV_I32));
|
||||
|
||||
// Signed remainder lib call names
|
||||
setLibcallName(RTLIB::SREM_I16, getIntrinsicName(RTLIB::SREM_I16));
|
||||
setLibcallName(RTLIB::SREM_I32, getIntrinsicName(RTLIB::SREM_I32));
|
||||
// Unsigned remainder lib call names
|
||||
setLibcallName(RTLIB::UREM_I16, getIntrinsicName(RTLIB::UREM_I16));
|
||||
setLibcallName(RTLIB::UREM_I32, getIntrinsicName(RTLIB::UREM_I32));
|
||||
|
||||
setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
|
||||
setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
|
||||
|
||||
@ -105,6 +129,7 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
|
||||
setOperationAction(ISD::ADDC, MVT::i8, Custom);
|
||||
setOperationAction(ISD::SUBE, MVT::i8, Custom);
|
||||
setOperationAction(ISD::SUBC, MVT::i8, Custom);
|
||||
setOperationAction(ISD::SUB, MVT::i8, Custom);
|
||||
setOperationAction(ISD::ADD, MVT::i8, Custom);
|
||||
setOperationAction(ISD::ADD, MVT::i16, Custom);
|
||||
|
||||
@ -354,21 +379,11 @@ SDValue PIC16TargetLowering::ExpandFrameIndex(SDNode *N, SelectionDAG &DAG) {
|
||||
FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(SDValue(N,0));
|
||||
// FIXME there isn't really debug info here
|
||||
DebugLoc dl = FR->getDebugLoc();
|
||||
// FIXME: Not used.
|
||||
// int Index = FR->getIndex();
|
||||
|
||||
// Expand FrameIndex like GlobalAddress and ExternalSymbol
|
||||
// Also use Offset field for lo and hi parts. The default
|
||||
// offset is zero.
|
||||
|
||||
/*
|
||||
SDValue Offset = DAG.getConstant(0, MVT::i8);
|
||||
SDValue FI = DAG.getTargetFrameIndex(Index, MVT::i8);
|
||||
SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, FI, Offset);
|
||||
SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, FI, Offset);
|
||||
return DAG.getNode(ISD::BUILD_PAIR, dl, N->getValueType(0), Lo, Hi);
|
||||
*/
|
||||
|
||||
SDValue ES;
|
||||
int FrameOffset;
|
||||
SDValue FI = SDValue(N,0);
|
||||
|
@ -227,15 +227,14 @@ PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM)
|
||||
setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand);
|
||||
setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom);
|
||||
setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand);
|
||||
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
|
||||
// This is just the low 32 bits of a (signed) fp->i64 conversion.
|
||||
// We cannot do this with Promote because i64 is not a legal type.
|
||||
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom);
|
||||
|
||||
// FIXME: disable this lowered code. This generates 64-bit register values,
|
||||
// and we don't model the fact that the top part is clobbered by calls. We
|
||||
// need to flag these together so that the value isn't live across a call.
|
||||
//setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom);
|
||||
|
||||
// To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT
|
||||
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote);
|
||||
} else {
|
||||
// PowerPC does not have FP_TO_UINT on 32-bit implementations.
|
||||
setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand);
|
||||
@ -2858,7 +2857,7 @@ SDValue PPCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) {
|
||||
}
|
||||
|
||||
// FIXME: Split this code up when LegalizeDAGTypes lands.
|
||||
SDValue PPCTargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG,
|
||||
SDValue PPCTargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG,
|
||||
DebugLoc dl) {
|
||||
assert(Op.getOperand(0).getValueType().isFloatingPoint());
|
||||
SDValue Src = Op.getOperand(0);
|
||||
@ -2867,9 +2866,11 @@ SDValue PPCTargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG,
|
||||
|
||||
SDValue Tmp;
|
||||
switch (Op.getValueType().getSimpleVT()) {
|
||||
default: assert(0 && "Unhandled FP_TO_SINT type in custom expander!");
|
||||
default: assert(0 && "Unhandled FP_TO_INT type in custom expander!");
|
||||
case MVT::i32:
|
||||
Tmp = DAG.getNode(PPCISD::FCTIWZ, dl, MVT::f64, Src);
|
||||
Tmp = DAG.getNode(Op.getOpcode()==ISD::FP_TO_SINT ? PPCISD::FCTIWZ :
|
||||
PPCISD::FCTIDZ,
|
||||
dl, MVT::f64, Src);
|
||||
break;
|
||||
case MVT::i64:
|
||||
Tmp = DAG.getNode(PPCISD::FCTIDZ, dl, MVT::f64, Src);
|
||||
@ -3740,7 +3741,8 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||
return LowerDYNAMIC_STACKALLOC(Op, DAG, PPCSubTarget);
|
||||
|
||||
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
|
||||
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG,
|
||||
case ISD::FP_TO_UINT:
|
||||
case ISD::FP_TO_SINT: return LowerFP_TO_INT(Op, DAG,
|
||||
Op.getDebugLoc());
|
||||
case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
|
||||
case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
|
||||
@ -3834,7 +3836,7 @@ void PPCTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||
return;
|
||||
}
|
||||
case ISD::FP_TO_SINT:
|
||||
Results.push_back(LowerFP_TO_SINT(SDValue(N, 0), DAG, dl));
|
||||
Results.push_back(LowerFP_TO_INT(SDValue(N, 0), DAG, dl));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ namespace llvm {
|
||||
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG,
|
||||
const PPCSubtarget &Subtarget);
|
||||
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG, DebugLoc dl);
|
||||
SDValue LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, DebugLoc dl);
|
||||
SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG);
|
||||
SDValue LowerSHL_PARTS(SDValue Op, SelectionDAG &DAG);
|
||||
|
@ -59,7 +59,7 @@ private:
|
||||
bool HasFastCall;
|
||||
|
||||
public:
|
||||
PPCFunctionInfo(MachineFunction &MF)
|
||||
explicit PPCFunctionInfo(MachineFunction &MF)
|
||||
: FramePointerSaveIndex(0),
|
||||
ReturnAddrSaveIndex(0),
|
||||
SpillsCR(false),
|
||||
|
@ -908,6 +908,7 @@ void PPCRegisterInfo::determineFrameLayout(MachineFunction &MF) const {
|
||||
// If we are a leaf function, and use up to 224 bytes of stack space,
|
||||
// don't have a frame pointer, calls, or dynamic alloca then we do not need
|
||||
// to adjust the stack pointer (we fit in the Red Zone).
|
||||
bool DisableRedZone = MF.getFunction()->hasFnAttr(Attribute::NoRedZone);
|
||||
if (!DisableRedZone &&
|
||||
FrameSize <= 224 && // Fits in red zone.
|
||||
!MFI->hasVarSizedObjects() && // No dynamic alloca.
|
||||
|
@ -41,7 +41,6 @@ namespace llvm {
|
||||
bool RealignStack;
|
||||
bool DisableJumpTables;
|
||||
bool StrongPHIElim;
|
||||
bool DisableRedZone;
|
||||
bool AsmVerbosityDefault(false);
|
||||
}
|
||||
|
||||
@ -86,11 +85,6 @@ GenerateSoftFloatCalls("soft-float",
|
||||
cl::location(UseSoftFloat),
|
||||
cl::init(false));
|
||||
static cl::opt<bool, true>
|
||||
GenerateNoImplicitFloats("no-implicit-float",
|
||||
cl::desc("Don't generate implicit floating point instructions (x86-only)"),
|
||||
cl::location(NoImplicitFloat),
|
||||
cl::init(false));
|
||||
static cl::opt<bool, true>
|
||||
DontPlaceZerosInBSS("nozero-initialized-in-bss",
|
||||
cl::desc("Don't place zero-initialized symbols into bss section"),
|
||||
cl::location(NoZerosInBSS),
|
||||
@ -163,11 +157,6 @@ EnableStrongPHIElim(cl::Hidden, "strong-phi-elim",
|
||||
cl::desc("Use strong PHI elimination."),
|
||||
cl::location(StrongPHIElim),
|
||||
cl::init(false));
|
||||
static cl::opt<bool, true>
|
||||
DisableRedZoneOption("disable-red-zone",
|
||||
cl::desc("Do not emit code that uses the red zone."),
|
||||
cl::location(DisableRedZone),
|
||||
cl::init(false));
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// TargetMachine Class
|
||||
|
@ -14,5 +14,6 @@
|
||||
#include "X86ELFWriterInfo.h"
|
||||
using namespace llvm;
|
||||
|
||||
X86ELFWriterInfo::X86ELFWriterInfo() : TargetELFWriterInfo(EM_386) {}
|
||||
X86ELFWriterInfo::X86ELFWriterInfo(bool is64Bit) :
|
||||
TargetELFWriterInfo(is64Bit ? EM_X86_64 : EM_386) {}
|
||||
X86ELFWriterInfo::~X86ELFWriterInfo() {}
|
||||
|
@ -20,7 +20,7 @@ namespace llvm {
|
||||
|
||||
class X86ELFWriterInfo : public TargetELFWriterInfo {
|
||||
public:
|
||||
X86ELFWriterInfo();
|
||||
X86ELFWriterInfo(bool is64Bit);
|
||||
virtual ~X86ELFWriterInfo();
|
||||
};
|
||||
|
||||
|
@ -126,7 +126,7 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
||||
setOperationAction(ISD::SINT_TO_FP , MVT::i1 , Promote);
|
||||
setOperationAction(ISD::SINT_TO_FP , MVT::i8 , Promote);
|
||||
|
||||
if (!UseSoftFloat && !NoImplicitFloat) {
|
||||
if (!UseSoftFloat) {
|
||||
// SSE has no i16 to fp conversion, only i32
|
||||
if (X86ScalarSSEf32) {
|
||||
setOperationAction(ISD::SINT_TO_FP , MVT::i16 , Promote);
|
||||
@ -550,6 +550,10 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
||||
setOperationAction(ISD::FLOG10, (MVT::SimpleValueType)VT, Expand);
|
||||
setOperationAction(ISD::FEXP, (MVT::SimpleValueType)VT, Expand);
|
||||
setOperationAction(ISD::FEXP2, (MVT::SimpleValueType)VT, Expand);
|
||||
setOperationAction(ISD::FP_TO_UINT, (MVT::SimpleValueType)VT, Expand);
|
||||
setOperationAction(ISD::FP_TO_SINT, (MVT::SimpleValueType)VT, Expand);
|
||||
setOperationAction(ISD::UINT_TO_FP, (MVT::SimpleValueType)VT, Expand);
|
||||
setOperationAction(ISD::SINT_TO_FP, (MVT::SimpleValueType)VT, Expand);
|
||||
}
|
||||
|
||||
// FIXME: In order to prevent SSE instructions being expanded to MMX ones
|
||||
@ -734,6 +738,12 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
||||
setOperationAction(ISD::SELECT, MVT::v2f64, Custom);
|
||||
setOperationAction(ISD::SELECT, MVT::v2i64, Custom);
|
||||
|
||||
setOperationAction(ISD::FP_TO_SINT, MVT::v4i32, Legal);
|
||||
setOperationAction(ISD::SINT_TO_FP, MVT::v4i32, Legal);
|
||||
if (!DisableMMX && Subtarget->hasMMX()) {
|
||||
setOperationAction(ISD::FP_TO_SINT, MVT::v2i32, Custom);
|
||||
setOperationAction(ISD::SINT_TO_FP, MVT::v2i32, Custom);
|
||||
}
|
||||
}
|
||||
|
||||
if (Subtarget->hasSSE41()) {
|
||||
@ -868,11 +878,14 @@ unsigned X86TargetLowering::getByValTypeAlignment(const Type *Ty) const {
|
||||
/// determining it.
|
||||
MVT
|
||||
X86TargetLowering::getOptimalMemOpType(uint64_t Size, unsigned Align,
|
||||
bool isSrcConst, bool isSrcStr) const {
|
||||
bool isSrcConst, bool isSrcStr,
|
||||
SelectionDAG &DAG) const {
|
||||
// FIXME: This turns off use of xmm stores for memset/memcpy on targets like
|
||||
// linux. This is because the stack realignment code can't handle certain
|
||||
// cases like PR2962. This should be removed when PR2962 is fixed.
|
||||
if (!NoImplicitFloat && Subtarget->getStackAlignment() >= 16) {
|
||||
const Function *F = DAG.getMachineFunction().getFunction();
|
||||
bool NoImplicitFloatOps = F->hasFnAttr(Attribute::NoImplicitFloat);
|
||||
if (!NoImplicitFloatOps && Subtarget->getStackAlignment() >= 16) {
|
||||
if ((isSrcConst || isSrcStr) && Subtarget->hasSSE2() && Size >= 16)
|
||||
return MVT::v4i32;
|
||||
if ((isSrcConst || isSrcStr) && Subtarget->hasSSE1() && Size >= 16)
|
||||
@ -1404,11 +1417,12 @@ X86TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG) {
|
||||
unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs,
|
||||
TotalNumXMMRegs);
|
||||
|
||||
bool NoImplicitFloatOps = Fn->hasFnAttr(Attribute::NoImplicitFloat);
|
||||
assert(!(NumXMMRegs && !Subtarget->hasSSE1()) &&
|
||||
"SSE register cannot be used when SSE is disabled!");
|
||||
assert(!(NumXMMRegs && UseSoftFloat && NoImplicitFloat) &&
|
||||
assert(!(NumXMMRegs && UseSoftFloat && NoImplicitFloatOps) &&
|
||||
"SSE register cannot be used when SSE is disabled!");
|
||||
if (UseSoftFloat || NoImplicitFloat || !Subtarget->hasSSE1())
|
||||
if (UseSoftFloat || NoImplicitFloatOps || !Subtarget->hasSSE1())
|
||||
// Kernel mode asks for SSE to be disabled, so don't push them
|
||||
// on the stack.
|
||||
TotalNumXMMRegs = 0;
|
||||
@ -2414,9 +2428,10 @@ bool X86::isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N) {
|
||||
/// specifies a shuffle of elements that is suitable for input to MOVSS,
|
||||
/// MOVSD, and MOVD, i.e. setting the lowest element.
|
||||
static bool isMOVLMask(const SmallVectorImpl<int> &Mask, MVT VT) {
|
||||
int NumElts = VT.getVectorNumElements();
|
||||
if (NumElts != 2 && NumElts != 4)
|
||||
if (VT.getVectorElementType().getSizeInBits() < 32)
|
||||
return false;
|
||||
|
||||
int NumElts = VT.getVectorNumElements();
|
||||
|
||||
if (!isUndefOrEqual(Mask[0], NumElts))
|
||||
return false;
|
||||
@ -3068,7 +3083,7 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
||||
}
|
||||
|
||||
// Special case for single non-zero, non-undef, element.
|
||||
if (NumNonZero == 1 && NumElems <= 4) {
|
||||
if (NumNonZero == 1) {
|
||||
unsigned Idx = CountTrailingZeros_32(NonZeros);
|
||||
SDValue Item = Op.getOperand(Idx);
|
||||
|
||||
@ -3109,15 +3124,24 @@ X86TargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) {
|
||||
// If we have a constant or non-constant insertion into the low element of
|
||||
// a vector, we can do this with SCALAR_TO_VECTOR + shuffle of zero into
|
||||
// the rest of the elements. This will be matched as movd/movq/movss/movsd
|
||||
// depending on what the source datatype is. Because we can only get here
|
||||
// when NumElems <= 4, this only needs to handle i32/f32/i64/f64.
|
||||
if (Idx == 0 &&
|
||||
// Don't do this for i64 values on x86-32.
|
||||
(EVT != MVT::i64 || Subtarget->is64Bit())) {
|
||||
Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Item);
|
||||
// Turn it into a MOVL (i.e. movss, movsd, or movd) to a zero vector.
|
||||
return getShuffleVectorZeroOrUndef(Item, 0, NumZero > 0,
|
||||
Subtarget->hasSSE2(), DAG);
|
||||
// depending on what the source datatype is.
|
||||
if (Idx == 0) {
|
||||
if (NumZero == 0) {
|
||||
return DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Item);
|
||||
} else if (EVT == MVT::i32 || EVT == MVT::f32 || EVT == MVT::f64 ||
|
||||
(EVT == MVT::i64 && Subtarget->is64Bit())) {
|
||||
Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, VT, Item);
|
||||
// Turn it into a MOVL (i.e. movss, movsd, or movd) to a zero vector.
|
||||
return getShuffleVectorZeroOrUndef(Item, 0, true, Subtarget->hasSSE2(),
|
||||
DAG);
|
||||
} else if (EVT == MVT::i16 || EVT == MVT::i8) {
|
||||
Item = DAG.getNode(ISD::ZERO_EXTEND, dl, MVT::i32, Item);
|
||||
MVT MiddleVT = VT.getSizeInBits() == 64 ? MVT::v2i32 : MVT::v4i32;
|
||||
Item = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, MiddleVT, Item);
|
||||
Item = getShuffleVectorZeroOrUndef(Item, 0, true,
|
||||
Subtarget->hasSSE2(), DAG);
|
||||
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, Item);
|
||||
}
|
||||
}
|
||||
|
||||
// Is it a vector logical left shift?
|
||||
@ -4248,7 +4272,7 @@ X86TargetLowering::LowerINSERT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) {
|
||||
SDValue N1 = Op.getOperand(1);
|
||||
SDValue N2 = Op.getOperand(2);
|
||||
|
||||
if (EVT.getSizeInBits() == 16) {
|
||||
if (EVT.getSizeInBits() == 16 && isa<ConstantSDNode>(N2)) {
|
||||
// Transform it so it match pinsrw which expects a 16-bit value in a GR32
|
||||
// as its second argument.
|
||||
if (N1.getValueType() != MVT::i32)
|
||||
@ -4554,6 +4578,14 @@ SDValue X86TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) {
|
||||
|
||||
SDValue X86TargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
|
||||
MVT SrcVT = Op.getOperand(0).getValueType();
|
||||
|
||||
if (SrcVT.isVector()) {
|
||||
if (SrcVT == MVT::v2i32 && Op.getValueType() == MVT::v2f64) {
|
||||
return Op;
|
||||
}
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
assert(SrcVT.getSimpleVT() <= MVT::i64 && SrcVT.getSimpleVT() >= MVT::i16 &&
|
||||
"Unknown SINT_TO_FP to lower!");
|
||||
|
||||
@ -4845,6 +4877,14 @@ FP_TO_INTHelper(SDValue Op, SelectionDAG &DAG, bool IsSigned) {
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) {
|
||||
if (Op.getValueType().isVector()) {
|
||||
if (Op.getValueType() == MVT::v2i32 &&
|
||||
Op.getOperand(0).getValueType() == MVT::v2f64) {
|
||||
return Op;
|
||||
}
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
std::pair<SDValue,SDValue> Vals = FP_TO_INTHelper(Op, DAG, true);
|
||||
SDValue FIST = Vals.first, StackSlot = Vals.second;
|
||||
// If FP_TO_INTHelper failed, the node is actually supposed to be Legal.
|
||||
@ -7675,8 +7715,9 @@ static bool EltsFromConsecutiveLoads(ShuffleVectorSDNode *N, unsigned NumElems,
|
||||
if (Elt.getOpcode() == ISD::UNDEF)
|
||||
continue;
|
||||
|
||||
if (!TLI.isConsecutiveLoad(Elt.getNode(), Base,
|
||||
EVT.getSizeInBits()/8, i, MFI))
|
||||
LoadSDNode *LD = cast<LoadSDNode>(Elt);
|
||||
LoadSDNode *LDBase = cast<LoadSDNode>(Base);
|
||||
if (!TLI.isConsecutiveLoad(LD, LDBase, EVT.getSizeInBits()/8, i, MFI))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -7751,44 +7792,82 @@ static SDValue PerformBuildVectorCombine(SDNode *N, SelectionDAG &DAG,
|
||||
|
||||
MVT VT = N->getValueType(0);
|
||||
MVT EVT = VT.getVectorElementType();
|
||||
if ((EVT != MVT::i64 && EVT != MVT::f64) || Subtarget->is64Bit())
|
||||
// We are looking for load i64 and zero extend. We want to transform
|
||||
// it before legalizer has a chance to expand it. Also look for i64
|
||||
// BUILD_PAIR bit casted to f64.
|
||||
return SDValue();
|
||||
// This must be an insertion into a zero vector.
|
||||
SDValue HighElt = N->getOperand(1);
|
||||
if (!isZeroNode(HighElt))
|
||||
return SDValue();
|
||||
|
||||
// Value must be a load.
|
||||
SDNode *Base = N->getOperand(0).getNode();
|
||||
if (!isa<LoadSDNode>(Base)) {
|
||||
if (Base->getOpcode() != ISD::BIT_CONVERT)
|
||||
|
||||
// Before or during type legalization, we want to try and convert a
|
||||
// build_vector of an i64 load and a zero value into vzext_movl before the
|
||||
// legalizer can break it up.
|
||||
// FIXME: does the case below remove the need to do this?
|
||||
if (DCI.isBeforeLegalize() || DCI.isCalledByLegalizer()) {
|
||||
if ((EVT != MVT::i64 && EVT != MVT::f64) || Subtarget->is64Bit())
|
||||
return SDValue();
|
||||
Base = Base->getOperand(0).getNode();
|
||||
if (!isa<LoadSDNode>(Base))
|
||||
|
||||
// This must be an insertion into a zero vector.
|
||||
SDValue HighElt = N->getOperand(1);
|
||||
if (!isZeroNode(HighElt))
|
||||
return SDValue();
|
||||
|
||||
// Value must be a load.
|
||||
SDNode *Base = N->getOperand(0).getNode();
|
||||
if (!isa<LoadSDNode>(Base)) {
|
||||
if (Base->getOpcode() != ISD::BIT_CONVERT)
|
||||
return SDValue();
|
||||
Base = Base->getOperand(0).getNode();
|
||||
if (!isa<LoadSDNode>(Base))
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
// Transform it into VZEXT_LOAD addr.
|
||||
LoadSDNode *LD = cast<LoadSDNode>(Base);
|
||||
|
||||
// Load must not be an extload.
|
||||
if (LD->getExtensionType() != ISD::NON_EXTLOAD)
|
||||
return SDValue();
|
||||
|
||||
// Load type should legal type so we don't have to legalize it.
|
||||
if (!TLI.isTypeLegal(VT))
|
||||
return SDValue();
|
||||
|
||||
SDVTList Tys = DAG.getVTList(VT, MVT::Other);
|
||||
SDValue Ops[] = { LD->getChain(), LD->getBasePtr() };
|
||||
SDValue ResNode = DAG.getNode(X86ISD::VZEXT_LOAD, dl, Tys, Ops, 2);
|
||||
TargetLowering::TargetLoweringOpt TLO(DAG);
|
||||
TLO.CombineTo(SDValue(Base, 1), ResNode.getValue(1));
|
||||
DCI.CommitTargetLoweringOpt(TLO);
|
||||
return ResNode;
|
||||
}
|
||||
|
||||
// Transform it into VZEXT_LOAD addr.
|
||||
LoadSDNode *LD = cast<LoadSDNode>(Base);
|
||||
// The type legalizer will have broken apart v2i64 build_vector created during
|
||||
// widening before the code which handles that case is run. Look for build
|
||||
// vector (load, load + 4, 0/undef, 0/undef)
|
||||
if (VT == MVT::v4i32 || VT == MVT::v4f32) {
|
||||
LoadSDNode *LD0 = dyn_cast<LoadSDNode>(N->getOperand(0));
|
||||
LoadSDNode *LD1 = dyn_cast<LoadSDNode>(N->getOperand(1));
|
||||
if (!LD0 || !LD1)
|
||||
return SDValue();
|
||||
if (LD0->getExtensionType() != ISD::NON_EXTLOAD ||
|
||||
LD1->getExtensionType() != ISD::NON_EXTLOAD)
|
||||
return SDValue();
|
||||
// Make sure the second elt is a consecutive load.
|
||||
if (!TLI.isConsecutiveLoad(LD1, LD0, EVT.getSizeInBits()/8, 1,
|
||||
DAG.getMachineFunction().getFrameInfo()))
|
||||
return SDValue();
|
||||
|
||||
// Load must not be an extload.
|
||||
if (LD->getExtensionType() != ISD::NON_EXTLOAD)
|
||||
return SDValue();
|
||||
|
||||
// Load type should legal type so we don't have to legalize it.
|
||||
if (!TLI.isTypeLegal(VT))
|
||||
return SDValue();
|
||||
|
||||
SDVTList Tys = DAG.getVTList(VT, MVT::Other);
|
||||
SDValue Ops[] = { LD->getChain(), LD->getBasePtr() };
|
||||
SDValue ResNode = DAG.getNode(X86ISD::VZEXT_LOAD, dl, Tys, Ops, 2);
|
||||
TargetLowering::TargetLoweringOpt TLO(DAG);
|
||||
TLO.CombineTo(SDValue(Base, 1), ResNode.getValue(1));
|
||||
DCI.CommitTargetLoweringOpt(TLO);
|
||||
return ResNode;
|
||||
SDValue N2 = N->getOperand(2);
|
||||
SDValue N3 = N->getOperand(3);
|
||||
if (!isZeroNode(N2) && N2.getOpcode() != ISD::UNDEF)
|
||||
return SDValue();
|
||||
if (!isZeroNode(N3) && N3.getOpcode() != ISD::UNDEF)
|
||||
return SDValue();
|
||||
|
||||
SDVTList Tys = DAG.getVTList(MVT::v2i64, MVT::Other);
|
||||
SDValue Ops[] = { LD0->getChain(), LD0->getBasePtr() };
|
||||
SDValue ResNode = DAG.getNode(X86ISD::VZEXT_LOAD, dl, Tys, Ops, 2);
|
||||
TargetLowering::TargetLoweringOpt TLO(DAG);
|
||||
TLO.CombineTo(SDValue(LD0, 1), ResNode.getValue(1));
|
||||
DCI.CommitTargetLoweringOpt(TLO);
|
||||
return DAG.getNode(ISD::BIT_CONVERT, dl, VT, ResNode);
|
||||
}
|
||||
return SDValue();
|
||||
}
|
||||
|
||||
/// PerformSELECTCombine - Do target-specific dag combines on SELECT nodes.
|
||||
@ -8242,7 +8321,10 @@ static SDValue PerformSTORECombine(SDNode *N, SelectionDAG &DAG,
|
||||
if (VT.getSizeInBits() != 64)
|
||||
return SDValue();
|
||||
|
||||
bool F64IsLegal = !UseSoftFloat && !NoImplicitFloat && Subtarget->hasSSE2();
|
||||
const Function *F = DAG.getMachineFunction().getFunction();
|
||||
bool NoImplicitFloatOps = F->hasFnAttr(Attribute::NoImplicitFloat);
|
||||
bool F64IsLegal = !UseSoftFloat && !NoImplicitFloatOps
|
||||
&& Subtarget->hasSSE2();
|
||||
if ((VT.isVector() ||
|
||||
(VT == MVT::i64 && F64IsLegal && !Subtarget->is64Bit())) &&
|
||||
isa<LoadSDNode>(St->getValue()) &&
|
||||
|
@ -378,7 +378,8 @@ namespace llvm {
|
||||
/// determining it.
|
||||
virtual
|
||||
MVT getOptimalMemOpType(uint64_t Size, unsigned Align,
|
||||
bool isSrcConst, bool isSrcStr) const;
|
||||
bool isSrcConst, bool isSrcStr,
|
||||
SelectionDAG &DAG) const;
|
||||
|
||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||
///
|
||||
|
@ -2009,16 +2009,24 @@ bool X86InstrInfo::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
|
||||
MachineFunction &MF = *MBB.getParent();
|
||||
X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
|
||||
X86FI->setCalleeSavedFrameSize(CSI.size() * SlotSize);
|
||||
unsigned CalleeFrameSize = 0;
|
||||
|
||||
unsigned Opc = is64Bit ? X86::PUSH64r : X86::PUSH32r;
|
||||
for (unsigned i = CSI.size(); i != 0; --i) {
|
||||
unsigned Reg = CSI[i-1].getReg();
|
||||
const TargetRegisterClass *RegClass = CSI[i-1].getRegClass();
|
||||
// Add the callee-saved register as live-in. It's killed at the spill.
|
||||
MBB.addLiveIn(Reg);
|
||||
BuildMI(MBB, MI, DL, get(Opc))
|
||||
.addReg(Reg, RegState::Kill);
|
||||
if (RegClass != &X86::VR128RegClass) {
|
||||
CalleeFrameSize += SlotSize;
|
||||
BuildMI(MBB, MI, DL, get(Opc))
|
||||
.addReg(Reg, RegState::Kill);
|
||||
} else {
|
||||
storeRegToStackSlot(MBB, MI, Reg, true, CSI[i-1].getFrameIdx(), RegClass);
|
||||
}
|
||||
}
|
||||
|
||||
X86FI->setCalleeSavedFrameSize(CalleeFrameSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2036,7 +2044,12 @@ bool X86InstrInfo::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
|
||||
unsigned Opc = is64Bit ? X86::POP64r : X86::POP32r;
|
||||
for (unsigned i = 0, e = CSI.size(); i != e; ++i) {
|
||||
unsigned Reg = CSI[i].getReg();
|
||||
BuildMI(MBB, MI, DL, get(Opc), Reg);
|
||||
const TargetRegisterClass *RegClass = CSI[i].getRegClass();
|
||||
if (RegClass != &X86::VR128RegClass) {
|
||||
BuildMI(MBB, MI, DL, get(Opc), Reg);
|
||||
} else {
|
||||
loadRegFromStackSlot(MBB, MI, Reg, CSI[i].getFrameIdx(), RegClass);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -577,41 +577,17 @@ def : Pat<(f64 (bitconvert (v4i16 VR64:$src))),
|
||||
def : Pat<(f64 (bitconvert (v8i8 VR64:$src))),
|
||||
(MMX_MOVQ2FR64rr VR64:$src)>;
|
||||
|
||||
// Move scalar to MMX zero-extended
|
||||
// movd to MMX register zero-extends
|
||||
let AddedComplexity = 15 in {
|
||||
def : Pat<(v8i8 (X86vzmovl (bc_v8i8 (v2i32 (scalar_to_vector GR32:$src))))),
|
||||
(MMX_MOVZDI2PDIrr GR32:$src)>;
|
||||
def : Pat<(v4i16 (X86vzmovl (bc_v4i16 (v2i32 (scalar_to_vector GR32:$src))))),
|
||||
(MMX_MOVZDI2PDIrr GR32:$src)>;
|
||||
}
|
||||
|
||||
let AddedComplexity = 20 in {
|
||||
def : Pat<(v8i8 (X86vzmovl (bc_v8i8 (load_mmx addr:$src)))),
|
||||
(MMX_MOVZDI2PDIrm addr:$src)>;
|
||||
def : Pat<(v4i16 (X86vzmovl (bc_v4i16 (load_mmx addr:$src)))),
|
||||
(MMX_MOVZDI2PDIrm addr:$src)>;
|
||||
def : Pat<(v2i32 (X86vzmovl (bc_v2i32 (load_mmx addr:$src)))),
|
||||
(MMX_MOVZDI2PDIrm addr:$src)>;
|
||||
}
|
||||
|
||||
// Clear top half.
|
||||
let AddedComplexity = 15 in {
|
||||
def : Pat<(v8i8 (X86vzmovl VR64:$src)),
|
||||
(MMX_PUNPCKLDQrr VR64:$src, (MMX_V_SET0))>;
|
||||
def : Pat<(v4i16 (X86vzmovl VR64:$src)),
|
||||
(MMX_PUNPCKLDQrr VR64:$src, (MMX_V_SET0))>;
|
||||
def : Pat<(v2i32 (X86vzmovl VR64:$src)),
|
||||
(MMX_PUNPCKLDQrr VR64:$src, (MMX_V_SET0))>;
|
||||
}
|
||||
|
||||
// Scalar to v4i16 / v8i8. The source may be a GR32, but only the lower
|
||||
// 8 or 16-bits matter.
|
||||
def : Pat<(bc_v8i8 (v2i32 (scalar_to_vector GR32:$src))),
|
||||
(MMX_MOVD64rr GR32:$src)>;
|
||||
def : Pat<(bc_v4i16 (v2i32 (scalar_to_vector GR32:$src))),
|
||||
(MMX_MOVD64rr GR32:$src)>;
|
||||
|
||||
// Patterns to perform canonical versions of vector shuffling.
|
||||
let AddedComplexity = 10 in {
|
||||
def : Pat<(v8i8 (mmx_unpckl_undef VR64:$src, (undef))),
|
||||
|
@ -3447,7 +3447,7 @@ multiclass SS41I_binop_rm_int2<bits<8> opc, string OpcodeStr, Intrinsic IntId> {
|
||||
}
|
||||
|
||||
defm PMOVSXBQ : SS41I_binop_rm_int2<0x22, "pmovsxbq", int_x86_sse41_pmovsxbq>;
|
||||
defm PMOVZXBQ : SS41I_binop_rm_int2<0x32, "pmovsxbq", int_x86_sse41_pmovzxbq>;
|
||||
defm PMOVZXBQ : SS41I_binop_rm_int2<0x32, "pmovzxbq", int_x86_sse41_pmovzxbq>;
|
||||
|
||||
// Common patterns involving scalar load
|
||||
def : Pat<(int_x86_sse41_pmovsxbq
|
||||
|
@ -73,14 +73,15 @@ public:
|
||||
SRetReturnReg(0),
|
||||
GlobalBaseReg(0) {}
|
||||
|
||||
X86MachineFunctionInfo(MachineFunction &MF) : ForceFramePointer(false),
|
||||
CalleeSavedFrameSize(0),
|
||||
BytesToPopOnReturn(0),
|
||||
DecorationStyle(None),
|
||||
ReturnAddrIndex(0),
|
||||
TailCallReturnAddrDelta(0),
|
||||
SRetReturnReg(0),
|
||||
GlobalBaseReg(0) {}
|
||||
explicit X86MachineFunctionInfo(MachineFunction &MF)
|
||||
: ForceFramePointer(false),
|
||||
CalleeSavedFrameSize(0),
|
||||
BytesToPopOnReturn(0),
|
||||
DecorationStyle(None),
|
||||
ReturnAddrIndex(0),
|
||||
TailCallReturnAddrDelta(0),
|
||||
SRetReturnReg(0),
|
||||
GlobalBaseReg(0) {}
|
||||
|
||||
bool getForceFramePointer() const { return ForceFramePointer;}
|
||||
void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; }
|
||||
|
@ -751,10 +751,12 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
// function, and use up to 128 bytes of stack space, don't have a frame
|
||||
// pointer, calls, or dynamic alloca then we do not need to adjust the
|
||||
// stack pointer (we fit in the Red Zone).
|
||||
bool DisableRedZone = Fn->hasFnAttr(Attribute::NoRedZone);
|
||||
if (Is64Bit && !DisableRedZone &&
|
||||
!needsStackRealignment(MF) &&
|
||||
!MFI->hasVarSizedObjects() && // No dynamic alloca.
|
||||
!MFI->hasCalls()) { // No calls.
|
||||
!MFI->hasCalls() && // No calls.
|
||||
!Subtarget->isTargetWin64()) { // Win64 has no Red Zone
|
||||
uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
|
||||
if (hasFP(MF)) MinSize += SlotSize;
|
||||
StackSize = std::max(MinSize,
|
||||
@ -820,13 +822,6 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
NumBytes = StackSize - X86FI->getCalleeSavedFrameSize();
|
||||
}
|
||||
|
||||
unsigned ReadyLabelId = 0;
|
||||
if (needsFrameMoves) {
|
||||
// Mark effective beginning of when frame pointer is ready.
|
||||
ReadyLabelId = MMI->NextLabelID();
|
||||
BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(ReadyLabelId);
|
||||
}
|
||||
|
||||
// Skip the callee-saved push instructions.
|
||||
while (MBBI != MBB.end() &&
|
||||
(MBBI->getOpcode() == X86::PUSH32r ||
|
||||
@ -836,20 +831,20 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
if (MBBI != MBB.end())
|
||||
DL = MBBI->getDebugLoc();
|
||||
|
||||
if (NumBytes) { // adjust stack pointer: ESP -= numbytes
|
||||
if (NumBytes) { // Adjust stack pointer: ESP -= numbytes.
|
||||
if (NumBytes >= 4096 && Subtarget->isTargetCygMing()) {
|
||||
// Check, whether EAX is livein for this function
|
||||
// Check, whether EAX is livein for this function.
|
||||
bool isEAXAlive = false;
|
||||
for (MachineRegisterInfo::livein_iterator
|
||||
II = MF.getRegInfo().livein_begin(),
|
||||
EE = MF.getRegInfo().livein_end(); (II != EE) && !isEAXAlive; ++II) {
|
||||
unsigned Reg = II->first;
|
||||
isEAXAlive = (Reg == X86::EAX || Reg == X86::AX ||
|
||||
Reg == X86::AH || Reg == X86::AL);
|
||||
Reg == X86::AH || Reg == X86::AL);
|
||||
}
|
||||
|
||||
// Function prologue calls _alloca to probe the stack when allocating
|
||||
// more than 4k bytes in one go. Touching the stack at 4K increments is
|
||||
// Function prologue calls _alloca to probe the stack when allocating more
|
||||
// than 4k bytes in one go. Touching the stack at 4K increments is
|
||||
// necessary to ensure that the guard pages used by the OS virtual memory
|
||||
// manager are allocated in correct sequence.
|
||||
if (!isEAXAlive) {
|
||||
@ -861,12 +856,14 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
// Save EAX
|
||||
BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH32r))
|
||||
.addReg(X86::EAX, RegState::Kill);
|
||||
|
||||
// Allocate NumBytes-4 bytes on stack. We'll also use 4 already
|
||||
// allocated bytes for EAX.
|
||||
BuildMI(MBB, MBBI, DL,
|
||||
TII.get(X86::MOV32ri), X86::EAX).addImm(NumBytes-4);
|
||||
BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX)
|
||||
.addImm(NumBytes-4);
|
||||
BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32))
|
||||
.addExternalSymbol("_alloca");
|
||||
|
||||
// Restore EAX
|
||||
MachineInstr *MI = addRegOffset(BuildMI(MF, DL, TII.get(X86::MOV32rm),
|
||||
X86::EAX),
|
||||
@ -878,6 +875,7 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
// merge the two. This can be the case when tail call elimination is
|
||||
// enabled and the callee has more arguments then the caller.
|
||||
NumBytes -= mergeSPUpdates(MBB, MBBI, StackPtr, true);
|
||||
|
||||
// If there is an ADD32ri or SUB32ri of ESP immediately after this
|
||||
// instruction, merge the two instructions.
|
||||
mergeSPUpdatesDown(MBB, MBBI, StackPtr, &NumBytes);
|
||||
@ -887,8 +885,13 @@ void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (needsFrameMoves)
|
||||
if (needsFrameMoves) {
|
||||
// Mark effective beginning of when frame pointer is ready.
|
||||
unsigned ReadyLabelId = 0;
|
||||
ReadyLabelId = MMI->NextLabelID();
|
||||
BuildMI(MBB, MBBI, DL, TII.get(X86::DBG_LABEL)).addImm(ReadyLabelId);
|
||||
emitFrameMoves(MF, FrameLabelId, ReadyLabelId);
|
||||
}
|
||||
}
|
||||
|
||||
void X86RegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
|
@ -133,7 +133,8 @@ X86TargetMachine::X86TargetMachine(const Module &M, const std::string &FS,
|
||||
DataLayout(Subtarget.getDataLayout()),
|
||||
FrameInfo(TargetFrameInfo::StackGrowsDown,
|
||||
Subtarget.getStackAlignment(), Subtarget.is64Bit() ? -8 : -4),
|
||||
InstrInfo(*this), JITInfo(*this), TLInfo(*this) {
|
||||
InstrInfo(*this), JITInfo(*this), TLInfo(*this),
|
||||
ELFWriterInfo(Subtarget.is64Bit()) {
|
||||
DefRelocModel = getRelocationModel();
|
||||
// FIXME: Correctly select PIC model for Win64 stuff
|
||||
if (getRelocationModel() == Reloc::Default) {
|
||||
@ -213,6 +214,13 @@ bool X86TargetMachine::addAssemblyEmitter(PassManagerBase &PM,
|
||||
CodeGenOpt::Level OptLevel,
|
||||
bool Verbose,
|
||||
raw_ostream &Out) {
|
||||
// FIXME: Move this somewhere else!
|
||||
// On Darwin, override 64-bit static relocation to pic_ since the
|
||||
// assembler doesn't support it.
|
||||
if (DefRelocModel == Reloc::Static &&
|
||||
Subtarget.isTargetDarwin() && Subtarget.is64Bit())
|
||||
setRelocationModel(Reloc::PIC_);
|
||||
|
||||
assert(AsmPrinterCtor && "AsmPrinter was not linked in");
|
||||
if (AsmPrinterCtor)
|
||||
PM.add(AsmPrinterCtor(Out, *this, OptLevel, Verbose));
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
FPSpillSlot(0),
|
||||
VarArgsFrameIndex(0) {}
|
||||
|
||||
XCoreFunctionInfo(MachineFunction &MF) :
|
||||
explicit XCoreFunctionInfo(MachineFunction &MF) :
|
||||
UsesLR(false),
|
||||
LRSpillSlot(0),
|
||||
FPSpillSlot(0),
|
||||
|
@ -59,7 +59,8 @@ cl::opt<bool> EnableLoadPRE("enable-load-pre", cl::init(true));
|
||||
/// two values.
|
||||
namespace {
|
||||
struct VISIBILITY_HIDDEN Expression {
|
||||
enum ExpressionOpcode { ADD, SUB, MUL, UDIV, SDIV, FDIV, UREM, SREM,
|
||||
enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL,
|
||||
UDIV, SDIV, FDIV, UREM, SREM,
|
||||
FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ,
|
||||
ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE,
|
||||
ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ,
|
||||
@ -200,8 +201,11 @@ Expression::ExpressionOpcode ValueTable::getOpcode(BinaryOperator* BO) {
|
||||
default: // THIS SHOULD NEVER HAPPEN
|
||||
assert(0 && "Binary operator with unknown opcode?");
|
||||
case Instruction::Add: return Expression::ADD;
|
||||
case Instruction::FAdd: return Expression::FADD;
|
||||
case Instruction::Sub: return Expression::SUB;
|
||||
case Instruction::FSub: return Expression::FSUB;
|
||||
case Instruction::Mul: return Expression::MUL;
|
||||
case Instruction::FMul: return Expression::FMUL;
|
||||
case Instruction::UDiv: return Expression::UDIV;
|
||||
case Instruction::SDiv: return Expression::SDIV;
|
||||
case Instruction::FDiv: return Expression::FDIV;
|
||||
|
@ -55,7 +55,8 @@ namespace {
|
||||
/// two values.
|
||||
|
||||
struct Expression {
|
||||
enum ExpressionOpcode { ADD, SUB, MUL, UDIV, SDIV, FDIV, UREM, SREM,
|
||||
enum ExpressionOpcode { ADD, FADD, SUB, FSUB, MUL, FMUL,
|
||||
UDIV, SDIV, FDIV, UREM, SREM,
|
||||
FREM, SHL, LSHR, ASHR, AND, OR, XOR, ICMPEQ,
|
||||
ICMPNE, ICMPUGT, ICMPUGE, ICMPULT, ICMPULE,
|
||||
ICMPSGT, ICMPSGE, ICMPSLT, ICMPSLE, FCMPOEQ,
|
||||
@ -202,10 +203,16 @@ Expression::ExpressionOpcode
|
||||
switch(BO->getOpcode()) {
|
||||
case Instruction::Add:
|
||||
return Expression::ADD;
|
||||
case Instruction::FAdd:
|
||||
return Expression::FADD;
|
||||
case Instruction::Sub:
|
||||
return Expression::SUB;
|
||||
case Instruction::FSub:
|
||||
return Expression::FSUB;
|
||||
case Instruction::Mul:
|
||||
return Expression::MUL;
|
||||
case Instruction::FMul:
|
||||
return Expression::FMUL;
|
||||
case Instruction::UDiv:
|
||||
return Expression::UDIV;
|
||||
case Instruction::SDiv:
|
||||
|
@ -754,7 +754,7 @@ void IndVarSimplify::HandleFloatingPointIV(Loop *L, PHINode *PH) {
|
||||
BinaryOperator *Incr =
|
||||
dyn_cast<BinaryOperator>(PH->getIncomingValue(BackEdge));
|
||||
if (!Incr) return;
|
||||
if (Incr->getOpcode() != Instruction::Add) return;
|
||||
if (Incr->getOpcode() != Instruction::FAdd) return;
|
||||
ConstantFP *IncrValue = NULL;
|
||||
unsigned IncrVIndex = 1;
|
||||
if (Incr->getOperand(1) == PH)
|
||||
|
@ -167,8 +167,11 @@ namespace {
|
||||
// otherwise - Change was made, replace I with returned instruction
|
||||
//
|
||||
Instruction *visitAdd(BinaryOperator &I);
|
||||
Instruction *visitFAdd(BinaryOperator &I);
|
||||
Instruction *visitSub(BinaryOperator &I);
|
||||
Instruction *visitFSub(BinaryOperator &I);
|
||||
Instruction *visitMul(BinaryOperator &I);
|
||||
Instruction *visitFMul(BinaryOperator &I);
|
||||
Instruction *visitURem(BinaryOperator &I);
|
||||
Instruction *visitSRem(BinaryOperator &I);
|
||||
Instruction *visitFRem(BinaryOperator &I);
|
||||
@ -403,7 +406,8 @@ X("instcombine", "Combine redundant instructions");
|
||||
// 0 -> undef, 1 -> Const, 2 -> Other, 3 -> Arg, 3 -> Unary, 4 -> OtherInst
|
||||
static unsigned getComplexity(Value *V) {
|
||||
if (isa<Instruction>(V)) {
|
||||
if (BinaryOperator::isNeg(V) || BinaryOperator::isNot(V))
|
||||
if (BinaryOperator::isNeg(V) || BinaryOperator::isFNeg(V) ||
|
||||
BinaryOperator::isNot(V))
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
@ -576,6 +580,25 @@ static inline Value *dyn_castNegVal(Value *V) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// dyn_castFNegVal - Given a 'fsub' instruction, return the RHS of the
|
||||
// instruction if the LHS is a constant negative zero (which is the 'negate'
|
||||
// form).
|
||||
//
|
||||
static inline Value *dyn_castFNegVal(Value *V) {
|
||||
if (BinaryOperator::isFNeg(V))
|
||||
return BinaryOperator::getFNegArgument(V);
|
||||
|
||||
// Constants can be considered to be negated values if they can be folded.
|
||||
if (ConstantFP *C = dyn_cast<ConstantFP>(V))
|
||||
return ConstantExpr::getFNeg(C);
|
||||
|
||||
if (ConstantVector *C = dyn_cast<ConstantVector>(V))
|
||||
if (C->getType()->getElementType()->isFloatingPoint())
|
||||
return ConstantExpr::getFNeg(C);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline Value *dyn_castNotVal(Value *V) {
|
||||
if (BinaryOperator::isNot(V))
|
||||
return BinaryOperator::getNotArgument(V);
|
||||
@ -1733,12 +1756,12 @@ Value *InstCombiner::SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
|
||||
default: assert(0 && "Case stmts out of sync!");
|
||||
case Intrinsic::x86_sse_sub_ss:
|
||||
case Intrinsic::x86_sse2_sub_sd:
|
||||
TmpV = InsertNewInstBefore(BinaryOperator::CreateSub(LHS, RHS,
|
||||
TmpV = InsertNewInstBefore(BinaryOperator::CreateFSub(LHS, RHS,
|
||||
II->getName()), *II);
|
||||
break;
|
||||
case Intrinsic::x86_sse_mul_ss:
|
||||
case Intrinsic::x86_sse2_mul_sd:
|
||||
TmpV = InsertNewInstBefore(BinaryOperator::CreateMul(LHS, RHS,
|
||||
TmpV = InsertNewInstBefore(BinaryOperator::CreateFMul(LHS, RHS,
|
||||
II->getName()), *II);
|
||||
break;
|
||||
}
|
||||
@ -2052,14 +2075,8 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
||||
return ReplaceInstUsesWith(I, RHS);
|
||||
|
||||
// X + 0 --> X
|
||||
if (!I.getType()->isFPOrFPVector()) { // NOTE: -0 + +0 = +0.
|
||||
if (RHSC->isNullValue())
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
} else if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
|
||||
if (CFP->isExactlyValue(ConstantFP::getNegativeZero
|
||||
(I.getType())->getValueAPF()))
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
}
|
||||
if (RHSC->isNullValue())
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(RHSC)) {
|
||||
// X + (signbit) --> X ^ signbit
|
||||
@ -2317,11 +2334,6 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
||||
return SelectInst::Create(SI->getCondition(), A, N);
|
||||
}
|
||||
}
|
||||
|
||||
// Check for X+0.0. Simplify it to X if we know X is not -0.0.
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHS))
|
||||
if (CFP->getValueAPF().isPosZero() && CannotBeNegativeZero(LHS))
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
|
||||
// Check for (add (sext x), y), see if we can merge this into an
|
||||
// integer add followed by a sext.
|
||||
@ -2359,7 +2371,42 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Changed ? &I : 0;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFAdd(BinaryOperator &I) {
|
||||
bool Changed = SimplifyCommutative(I);
|
||||
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
|
||||
|
||||
if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
|
||||
// X + 0 --> X
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHSC)) {
|
||||
if (CFP->isExactlyValue(ConstantFP::getNegativeZero
|
||||
(I.getType())->getValueAPF()))
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
}
|
||||
|
||||
if (isa<PHINode>(LHS))
|
||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||
return NV;
|
||||
}
|
||||
|
||||
// -A + B --> B - A
|
||||
// -A + -B --> -(A + B)
|
||||
if (Value *LHSV = dyn_castFNegVal(LHS))
|
||||
return BinaryOperator::CreateFSub(RHS, LHSV);
|
||||
|
||||
// A + -B --> A - B
|
||||
if (!isa<Constant>(RHS))
|
||||
if (Value *V = dyn_castFNegVal(RHS))
|
||||
return BinaryOperator::CreateFSub(LHS, V);
|
||||
|
||||
// Check for X+0.0. Simplify it to X if we know X is not -0.0.
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(RHS))
|
||||
if (CFP->getValueAPF().isPosZero() && CannotBeNegativeZero(LHS))
|
||||
return ReplaceInstUsesWith(I, LHS);
|
||||
|
||||
// Check for (add double (sitofp x), y), see if we can merge this into an
|
||||
// integer add followed by a promotion.
|
||||
if (SIToFPInst *LHSConv = dyn_cast<SIToFPInst>(LHS)) {
|
||||
@ -2407,8 +2454,7 @@ Instruction *InstCombiner::visitAdd(BinaryOperator &I) {
|
||||
Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
if (Op0 == Op1 && // sub X, X -> 0
|
||||
!I.getType()->isFPOrFPVector())
|
||||
if (Op0 == Op1) // sub X, X -> 0
|
||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||
|
||||
// If this is a 'B = x-(-A)', change to B = x+A...
|
||||
@ -2469,8 +2515,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
return BinaryOperator::CreateXor(Op0, Op1);
|
||||
|
||||
if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1)) {
|
||||
if (Op1I->getOpcode() == Instruction::Add &&
|
||||
!Op0->getType()->isFPOrFPVector()) {
|
||||
if (Op1I->getOpcode() == Instruction::Add) {
|
||||
if (Op1I->getOperand(0) == Op0) // X-(X+Y) == -Y
|
||||
return BinaryOperator::CreateNeg(Op1I->getOperand(1), I.getName());
|
||||
else if (Op1I->getOperand(1) == Op0) // X-(Y+X) == -Y
|
||||
@ -2487,8 +2532,7 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
// Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression
|
||||
// is not used by anyone else...
|
||||
//
|
||||
if (Op1I->getOpcode() == Instruction::Sub &&
|
||||
!Op1I->getType()->isFPOrFPVector()) {
|
||||
if (Op1I->getOpcode() == Instruction::Sub) {
|
||||
// Swap the two operands of the subexpr...
|
||||
Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1);
|
||||
Op1I->setOperand(0, IIOp1);
|
||||
@ -2526,18 +2570,17 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!Op0->getType()->isFPOrFPVector())
|
||||
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
|
||||
if (Op0I->getOpcode() == Instruction::Add) {
|
||||
if (Op0I->getOperand(0) == Op1) // (Y+X)-Y == X
|
||||
return ReplaceInstUsesWith(I, Op0I->getOperand(1));
|
||||
else if (Op0I->getOperand(1) == Op1) // (X+Y)-Y == X
|
||||
return ReplaceInstUsesWith(I, Op0I->getOperand(0));
|
||||
} else if (Op0I->getOpcode() == Instruction::Sub) {
|
||||
if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y
|
||||
return BinaryOperator::CreateNeg(Op0I->getOperand(1), I.getName());
|
||||
}
|
||||
if (BinaryOperator *Op0I = dyn_cast<BinaryOperator>(Op0)) {
|
||||
if (Op0I->getOpcode() == Instruction::Add) {
|
||||
if (Op0I->getOperand(0) == Op1) // (Y+X)-Y == X
|
||||
return ReplaceInstUsesWith(I, Op0I->getOperand(1));
|
||||
else if (Op0I->getOperand(1) == Op1) // (X+Y)-Y == X
|
||||
return ReplaceInstUsesWith(I, Op0I->getOperand(0));
|
||||
} else if (Op0I->getOpcode() == Instruction::Sub) {
|
||||
if (Op0I->getOperand(0) == Op1) // (X-Y)-X == -Y
|
||||
return BinaryOperator::CreateNeg(Op0I->getOperand(1), I.getName());
|
||||
}
|
||||
}
|
||||
|
||||
ConstantInt *C1;
|
||||
if (Value *X = dyn_castFoldableMul(Op0, C1)) {
|
||||
@ -2551,6 +2594,40 @@ Instruction *InstCombiner::visitSub(BinaryOperator &I) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFSub(BinaryOperator &I) {
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
||||
// If this is a 'B = x-(-A)', change to B = x+A...
|
||||
if (Value *V = dyn_castFNegVal(Op1))
|
||||
return BinaryOperator::CreateFAdd(Op0, V);
|
||||
|
||||
if (BinaryOperator *Op1I = dyn_cast<BinaryOperator>(Op1)) {
|
||||
if (Op1I->getOpcode() == Instruction::FAdd) {
|
||||
if (Op1I->getOperand(0) == Op0) // X-(X+Y) == -Y
|
||||
return BinaryOperator::CreateFNeg(Op1I->getOperand(1), I.getName());
|
||||
else if (Op1I->getOperand(1) == Op0) // X-(Y+X) == -Y
|
||||
return BinaryOperator::CreateFNeg(Op1I->getOperand(0), I.getName());
|
||||
}
|
||||
|
||||
if (Op1I->hasOneUse()) {
|
||||
// Replace (x - (y - z)) with (x + (z - y)) if the (y - z) subexpression
|
||||
// is not used by anyone else...
|
||||
//
|
||||
if (Op1I->getOpcode() == Instruction::FSub) {
|
||||
// Swap the two operands of the subexpr...
|
||||
Value *IIOp0 = Op1I->getOperand(0), *IIOp1 = Op1I->getOperand(1);
|
||||
Op1I->setOperand(0, IIOp1);
|
||||
Op1I->setOperand(1, IIOp0);
|
||||
|
||||
// Create the new top level fadd instruction...
|
||||
return BinaryOperator::CreateFAdd(Op0, Op1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// isSignBitCheck - Given an exploded icmp instruction, return true if the
|
||||
/// comparison only checks the sign bit. If it only checks the sign bit, set
|
||||
/// TrueIfSigned if the result of the comparison is true when the input value is
|
||||
@ -2585,7 +2662,9 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||
bool Changed = SimplifyCommutative(I);
|
||||
Value *Op0 = I.getOperand(0);
|
||||
|
||||
if (isa<UndefValue>(I.getOperand(1))) // undef * X -> 0
|
||||
// TODO: If Op1 is undef and Op0 is finite, return zero.
|
||||
if (!I.getType()->isFPOrFPVector() &&
|
||||
isa<UndefValue>(I.getOperand(1))) // undef * X -> 0
|
||||
return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
|
||||
|
||||
// Simplify mul instructions with a constant RHS...
|
||||
@ -2611,17 +2690,8 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||
return BinaryOperator::CreateShl(Op0,
|
||||
ConstantInt::get(Op0->getType(), Val.logBase2()));
|
||||
}
|
||||
} else if (ConstantFP *Op1F = dyn_cast<ConstantFP>(Op1)) {
|
||||
if (Op1F->isNullValue())
|
||||
return ReplaceInstUsesWith(I, Op1);
|
||||
|
||||
// "In IEEE floating point, x*1 is not equivalent to x for nans. However,
|
||||
// ANSI says we can drop signals, so we can do this anyway." (from GCC)
|
||||
if (Op1F->isExactlyValue(1.0))
|
||||
return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0'
|
||||
} else if (isa<VectorType>(Op1->getType())) {
|
||||
if (isa<ConstantAggregateZero>(Op1))
|
||||
return ReplaceInstUsesWith(I, Op1);
|
||||
// TODO: If Op1 is all zeros and Op0 is all finite, return all zeros.
|
||||
|
||||
if (ConstantVector *Op1V = dyn_cast<ConstantVector>(Op1)) {
|
||||
if (Op1V->isAllOnesValue()) // X * -1 == 0 - X
|
||||
@ -2629,9 +2699,6 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||
|
||||
// As above, vector X*splat(1.0) -> X in all defined cases.
|
||||
if (Constant *Splat = Op1V->getSplatValue()) {
|
||||
if (ConstantFP *F = dyn_cast<ConstantFP>(Splat))
|
||||
if (F->isExactlyValue(1.0))
|
||||
return ReplaceInstUsesWith(I, Op0);
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(Splat))
|
||||
if (CI->equalsInt(1))
|
||||
return ReplaceInstUsesWith(I, Op0);
|
||||
@ -2755,6 +2822,45 @@ Instruction *InstCombiner::visitMul(BinaryOperator &I) {
|
||||
return Changed ? &I : 0;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFMul(BinaryOperator &I) {
|
||||
bool Changed = SimplifyCommutative(I);
|
||||
Value *Op0 = I.getOperand(0);
|
||||
|
||||
// Simplify mul instructions with a constant RHS...
|
||||
if (Constant *Op1 = dyn_cast<Constant>(I.getOperand(1))) {
|
||||
if (ConstantFP *Op1F = dyn_cast<ConstantFP>(Op1)) {
|
||||
// "In IEEE floating point, x*1 is not equivalent to x for nans. However,
|
||||
// ANSI says we can drop signals, so we can do this anyway." (from GCC)
|
||||
if (Op1F->isExactlyValue(1.0))
|
||||
return ReplaceInstUsesWith(I, Op0); // Eliminate 'mul double %X, 1.0'
|
||||
} else if (isa<VectorType>(Op1->getType())) {
|
||||
if (ConstantVector *Op1V = dyn_cast<ConstantVector>(Op1)) {
|
||||
// As above, vector X*splat(1.0) -> X in all defined cases.
|
||||
if (Constant *Splat = Op1V->getSplatValue()) {
|
||||
if (ConstantFP *F = dyn_cast<ConstantFP>(Splat))
|
||||
if (F->isExactlyValue(1.0))
|
||||
return ReplaceInstUsesWith(I, Op0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to fold constant mul into select arguments.
|
||||
if (SelectInst *SI = dyn_cast<SelectInst>(Op0))
|
||||
if (Instruction *R = FoldOpIntoSelect(I, SI, this))
|
||||
return R;
|
||||
|
||||
if (isa<PHINode>(Op0))
|
||||
if (Instruction *NV = FoldOpIntoPhi(I))
|
||||
return NV;
|
||||
}
|
||||
|
||||
if (Value *Op0v = dyn_castFNegVal(Op0)) // -X * -Y = X*Y
|
||||
if (Value *Op1v = dyn_castFNegVal(I.getOperand(1)))
|
||||
return BinaryOperator::CreateFMul(Op0v, Op1v);
|
||||
|
||||
return Changed ? &I : 0;
|
||||
}
|
||||
|
||||
/// SimplifyDivRemOfSelect - Try to fold a divide or remainder of a select
|
||||
/// instruction.
|
||||
bool InstCombiner::SimplifyDivRemOfSelect(BinaryOperator &I) {
|
||||
@ -8562,17 +8668,17 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &CI) {
|
||||
if (Instruction *I = commonCastTransforms(CI))
|
||||
return I;
|
||||
|
||||
// If we have fptrunc(add (fpextend x), (fpextend y)), where x and y are
|
||||
// If we have fptrunc(fadd (fpextend x), (fpextend y)), where x and y are
|
||||
// smaller than the destination type, we can eliminate the truncate by doing
|
||||
// the add as the smaller type. This applies to add/sub/mul/div as well as
|
||||
// the add as the smaller type. This applies to fadd/fsub/fmul/fdiv as well as
|
||||
// many builtins (sqrt, etc).
|
||||
BinaryOperator *OpI = dyn_cast<BinaryOperator>(CI.getOperand(0));
|
||||
if (OpI && OpI->hasOneUse()) {
|
||||
switch (OpI->getOpcode()) {
|
||||
default: break;
|
||||
case Instruction::Add:
|
||||
case Instruction::Sub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::FAdd:
|
||||
case Instruction::FSub:
|
||||
case Instruction::FMul:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::FRem:
|
||||
const Type *SrcTy = OpI->getType();
|
||||
@ -9322,11 +9428,15 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
||||
|
||||
// Turn select C, (X+Y), (X-Y) --> (X+(select C, Y, (-Y))). This is
|
||||
// even legal for FP.
|
||||
if (TI->getOpcode() == Instruction::Sub &&
|
||||
FI->getOpcode() == Instruction::Add) {
|
||||
if ((TI->getOpcode() == Instruction::Sub &&
|
||||
FI->getOpcode() == Instruction::Add) ||
|
||||
(TI->getOpcode() == Instruction::FSub &&
|
||||
FI->getOpcode() == Instruction::FAdd)) {
|
||||
AddOp = FI; SubOp = TI;
|
||||
} else if (FI->getOpcode() == Instruction::Sub &&
|
||||
TI->getOpcode() == Instruction::Add) {
|
||||
} else if ((FI->getOpcode() == Instruction::Sub &&
|
||||
TI->getOpcode() == Instruction::Add) ||
|
||||
(FI->getOpcode() == Instruction::FSub &&
|
||||
TI->getOpcode() == Instruction::FAdd)) {
|
||||
AddOp = TI; SubOp = FI;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user