Import LLVM, at r72995.

We should now have support for #pragma weak.
This commit is contained in:
Ed Schouten 2009-06-06 08:20:29 +00:00
parent 68eb509bdc
commit f4fe016fa1
372 changed files with 4344 additions and 2881 deletions

View File

@ -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()

View File

@ -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)),)

View File

@ -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===

View File

@ -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)

View File

@ -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})

View File

@ -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)

View File

@ -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
View File

@ -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

View File

@ -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>

View File

@ -153,9 +153,18 @@ $ llvm-gcc -use-gold-plugin a.o b.o -o main # &lt;-- 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>

View File

@ -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>
&lt;result&gt; = fadd &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <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>
&lt;result&gt; = 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>
&lt;result&gt; = fsub &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <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>
&lt;result&gt; = fsub float 4.0, %var <i>; yields {float}:result = 4.0 - %var</i>
&lt;result&gt; = 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> &lt;result&gt; = fmul &lt;ty&gt; &lt;op1&gt;, &lt;op2&gt; <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> &lt;result&gt; = 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* &lt;guard&gt;, i8** &lt;slot&gt; )
<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>

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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))

View File

@ -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);
}

View File

@ -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
//

View File

@ -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.

View File

@ -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));
}

View File

@ -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.

View File

@ -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();
/// @}
};
}

View File

@ -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) {}

View File

@ -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

View File

@ -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

View File

@ -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)");

View File

@ -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;

View File

@ -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.

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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:

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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() {

View File

@ -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
View 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

View File

@ -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;
}

View File

@ -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);

View File

@ -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!

View File

@ -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);

View File

@ -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;
//===----------------------------------------------------------------------===//

View File

@ -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';

View File

@ -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);

View File

@ -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:

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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());

View File

@ -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) {

View File

@ -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); }

View File

@ -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;

View File

@ -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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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");

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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";
}

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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;

View File

@ -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),

View File

@ -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.

View File

@ -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; }

View File

@ -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;

View File

@ -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;

View File

@ -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; };
};

View File

@ -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:

View File

@ -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; }

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);

View File

@ -59,7 +59,7 @@ private:
bool HasFastCall;
public:
PPCFunctionInfo(MachineFunction &MF)
explicit PPCFunctionInfo(MachineFunction &MF)
: FramePointerSaveIndex(0),
ReturnAddrSaveIndex(0),
SpillsCR(false),

View File

@ -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.

View File

@ -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

View File

@ -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() {}

View File

@ -20,7 +20,7 @@ namespace llvm {
class X86ELFWriterInfo : public TargetELFWriterInfo {
public:
X86ELFWriterInfo();
X86ELFWriterInfo(bool is64Bit);
virtual ~X86ELFWriterInfo();
};

View File

@ -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()) &&

View File

@ -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.
///

View File

@ -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;
}

View File

@ -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))),

View File

@ -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

View File

@ -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; }

View File

@ -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,

View File

@ -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));

View File

@ -40,7 +40,7 @@ public:
FPSpillSlot(0),
VarArgsFrameIndex(0) {}
XCoreFunctionInfo(MachineFunction &MF) :
explicit XCoreFunctionInfo(MachineFunction &MF) :
UsesLR(false),
LRSpillSlot(0),
FPSpillSlot(0),

View File

@ -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;

View File

@ -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:

View File

@ -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)

View File

@ -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