Updating branches/google/testing to r243773

git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/google/testing@243815 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Alexey Samsonov 2015-08-01 00:04:09 +00:00
commit d33a944a7d
2628 changed files with 140689 additions and 40698 deletions

2
.gitignore vendored
View File

@ -44,7 +44,7 @@ autoconf/autom4te.cache
#==============================================================================#
# External projects that are tracked independently.
projects/*
!projects/CMakeLists.txt
!projects/*.*
!projects/Makefile
# Clang, which is tracked independently.
tools/clang

View File

@ -26,7 +26,7 @@ else()
set(cmake_3_2_USES_TERMINAL USES_TERMINAL)
endif()
project(LLVM)
project(LLVM C CXX ASM)
# The following only works with the Ninja generator in CMake >= 3.0.
set(LLVM_PARALLEL_COMPILE_JOBS "" CACHE STRING
@ -59,7 +59,7 @@ set(CMAKE_MODULE_PATH
)
set(LLVM_VERSION_MAJOR 3)
set(LLVM_VERSION_MINOR 7)
set(LLVM_VERSION_MINOR 8)
set(LLVM_VERSION_PATCH 0)
set(LLVM_VERSION_SUFFIX svn)
@ -530,7 +530,7 @@ endif()
# check its symbols. This is wasteful (the check was done when foo.so
# was created) and can fail since it is not the dynamic linker and
# doesn't know how to handle search paths correctly.
if (UNIX AND NOT APPLE)
if (UNIX AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -Wl,-allow-shlib-undefined")
endif()

View File

@ -65,6 +65,10 @@ N: Hal Finkel
E: hfinkel@anl.gov
D: BBVectorize, the loop reroller, alias analysis and the PowerPC target
N: Dan Gohman
E: sunfish@mozilla.com
D: WebAssembly Backend (lib/Target/WebAssembly/*)
N: Renato Golin
E: renato.golin@linaro.org
D: ARM Linux support

View File

@ -152,8 +152,9 @@ E: foldr@codedgers.com
D: Author of llvmc2
N: Dan Gohman
E: dan433584@gmail.com
E: sunfish@mozilla.com
D: Miscellaneous bug fixes
D: WebAssembly Backend
N: David Goodwin
E: david@goodwinz.net

View File

@ -58,20 +58,9 @@ LLVM_OBJ_ROOT := $(call realpath, @abs_top_builddir@)
PROJ_SRC_ROOT := $(LLVM_SRC_ROOT)
PROJ_SRC_DIR := $(LLVM_SRC_ROOT)$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR))
# FIXME: This is temporary during the grace period where in-source builds are
# deprecated. Convert to a hard error when that period is up.
#
# See: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150323/268067.html
ifeq ($(LLVM_SRC_ROOT), $(LLVM_OBJ_ROOT))
$(warning ######################################################################################)
$(warning # #)
$(warning # WARNING #)
$(warning # #)
$(warning # In-source builds are deprecated. #)
$(warning # #)
$(warning # Please configure from a separate build directory! #)
$(warning # #)
$(warning ######################################################################################)
$(error In-source builds are not allowed. Please configure from a separate build directory!)
endif
ifneq ($(CLANG_SRC_ROOT),)

View File

@ -810,6 +810,9 @@ EOF
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32

View File

@ -32,10 +32,10 @@ dnl===-----------------------------------------------------------------------===
dnl Initialize autoconf and define the package name, version number and
dnl address for reporting bugs.
AC_INIT([LLVM],[3.7.0svn],[http://llvm.org/bugs/])
AC_INIT([LLVM],[3.8.0svn],[http://llvm.org/bugs/])
LLVM_VERSION_MAJOR=3
LLVM_VERSION_MINOR=7
LLVM_VERSION_MINOR=8
LLVM_VERSION_PATCH=0
LLVM_VERSION_SUFFIX=svn
@ -75,15 +75,7 @@ fi
dnl Quit if it is an in-source build
if test ${srcdir} == "." ; then
AC_MSG_WARN([**************************************************************************************])
AC_MSG_WARN([* *])
AC_MSG_WARN([* WARNING *])
AC_MSG_WARN([* *])
AC_MSG_WARN([* In-source builds are deprecated. *])
AC_MSG_WARN([* *])
AC_MSG_WARN([* Please configure from a separate build directory! *])
AC_MSG_WARN([* *])
AC_MSG_WARN([**************************************************************************************])
AC_MSG_ERROR([In-source builds are not allowed. Please configure from a separate build directory!])
fi
dnl Default to empty (i.e. assigning the null string to) CFLAGS and CXXFLAGS,
@ -445,6 +437,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch],
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
nvptx-*) llvm_cv_target_arch="NVPTX" ;;
s390x-*) llvm_cv_target_arch="SystemZ" ;;
wasm*-*) llvm_cv_target_arch="WebAssembly" ;;
*) llvm_cv_target_arch="Unknown" ;;
esac])
@ -480,6 +473,7 @@ case $host in
msp430-*) host_arch="MSP430" ;;
hexagon-*) host_arch="Hexagon" ;;
s390x-*) host_arch="SystemZ" ;;
wasm*-*) host_arch="WebAssembly" ;;
*) host_arch="Unknown" ;;
esac
@ -812,6 +806,7 @@ else
Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;;
NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;;
SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;;
WebAssembly) AC_SUBST(TARGET_HAS_JIT,0) ;;
*) AC_SUBST(TARGET_HAS_JIT,0) ;;
esac
fi
@ -1105,7 +1100,7 @@ TARGETS_TO_BUILD=""
AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets],
[Build specific host targets: all or target1,target2,... Valid targets are:
host, x86, x86_64, sparc, powerpc, arm64, arm, aarch64, mips, hexagon,
xcore, msp430, nvptx, systemz, r600, bpf, and cpp (default=all)]),,
xcore, msp430, nvptx, systemz, r600, bpf, wasm, and cpp (default=all)]),,
enableval=all)
if test "$enableval" = host-only ; then
enableval=host
@ -1134,6 +1129,7 @@ case "$enableval" in
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
r600) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
wasm) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;;
host) case "$llvm_cv_target_arch" in
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
@ -1147,6 +1143,7 @@ case "$enableval" in
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
WebAssembly) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;;
*) AC_MSG_ERROR([Can not set target to build]) ;;
esac ;;
*) AC_MSG_ERROR([Unrecognized target $a_target]) ;;
@ -1631,7 +1628,7 @@ dnl===-----------------------------------------------------------------------===
AC_CHECK_LIB(m,sin)
if test "$llvm_cv_os_type" = "MingW" ; then
AC_CHECK_LIB(imagehlp, main)
AC_CHECK_LIB(ole32, main)
AC_CHECK_LIB(psapi, main)
AC_CHECK_LIB(shell32, main)
fi
@ -2172,7 +2169,10 @@ dnl contains the same list of files as AC_CONFIG_HEADERS below. This ensures the
dnl files can be updated automatically when their *.in sources change.
AC_CONFIG_HEADERS([include/llvm/Config/config.h include/llvm/Config/llvm-config.h])
AH_TOP([#ifndef CONFIG_H
#define CONFIG_H])
#define CONFIG_H
/* Exported configuration */
#include "llvm/Config/llvm-config.h"])
AH_BOTTOM([#endif])
AC_CONFIG_FILES([include/llvm/Config/Targets.def])

View File

@ -84,13 +84,18 @@ LLVMMetadataRef LLVMDIBuilderCreateFunction(
}
LLVMMetadataRef LLVMDIBuilderCreateLocalVariable(
LLVMDIBuilderRef Dref, unsigned Tag, LLVMMetadataRef Scope,
LLVMDIBuilderRef Dref, unsigned, LLVMMetadataRef Scope,
const char *Name, LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty,
int AlwaysPreserve, unsigned Flags, unsigned ArgNo) {
DIBuilder *D = unwrap(Dref);
return wrap(D->createLocalVariable(
Tag, unwrap<DIScope>(Scope), Name, unwrap<DIFile>(File), Line,
unwrap<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
// FIXME: Update the Go bindings to match the DIBuilder API.
if (ArgNo)
return wrap(D->createParameterVariable(
unwrap<DIScope>(Scope), Name, ArgNo, unwrap<DIFile>(File), Line,
unwrap<DIType>(Ty), AlwaysPreserve, Flags));
return wrap(D->createAutoVariable(unwrap<DIScope>(Scope), Name,
unwrap<DIFile>(File), Line,
unwrap<DIType>(Ty), AlwaysPreserve, Flags));
}
LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref,

View File

@ -160,6 +160,8 @@ const (
InAllocaAttribute Attribute = 1 << 43
NonNullAttribute Attribute = 1 << 44
JumpTableAttribute Attribute = 1 << 45
ConvergentAttribute Attribute = 1 << 46
SafeStackAttribute Attribute = 1 << 47
)
//-------------------------------------------------------------------------
@ -1052,6 +1054,9 @@ func (v Value) AddTargetDependentFunctionAttr(attr, value string) {
defer C.free(unsafe.Pointer(cvalue))
C.LLVMAddTargetDependentFunctionAttr(v.C, cattr, cvalue)
}
func (v Value) SetPersonality(p Value) {
C.LLVMSetPersonalityFn(v.C, p.C)
}
// Operations on parameters
func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) }
@ -1204,7 +1209,7 @@ func (b Builder) Dispose() { C.LLVMDisposeBuilder(b.C) }
func (b Builder) SetCurrentDebugLocation(line, col uint, scope, inlinedAt Metadata) {
C.LLVMSetCurrentDebugLocation2(b.C, C.unsigned(line), C.unsigned(col), scope.C, inlinedAt.C)
}
func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) }
func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) }
func (b Builder) InsertDeclare(module Module, storage Value, md Value) Value {
f := module.NamedFunction("llvm.dbg.declare")
if f.IsNil() {
@ -1723,10 +1728,10 @@ func (b Builder) CreatePtrDiff(lhs, rhs Value, name string) (v Value) {
return
}
func (b Builder) CreateLandingPad(t Type, personality Value, nclauses int, name string) (l Value) {
func (b Builder) CreateLandingPad(t Type, nclauses int, name string) (l Value) {
cname := C.CString(name)
defer C.free(unsafe.Pointer(cname))
l.C = C.LLVMBuildLandingPad(b.C, t.C, personality.C, C.unsigned(nclauses), cname)
l.C = C.LLVMBuildLandingPad(b.C, t.C, nil, C.unsigned(nclauses), cname)
return l
}

View File

@ -53,6 +53,7 @@ func TestAttributes(t *testing.T) {
{AlwaysInlineAttribute, "alwaysinline"},
{BuiltinAttribute, "builtin"},
{ByValAttribute, "byval"},
{ConvergentAttribute, "convergent"},
{InAllocaAttribute, "inalloca"},
{InlineHintAttribute, "inlinehint"},
{InRegAttribute, "inreg"},
@ -78,6 +79,7 @@ func TestAttributes(t *testing.T) {
{ReturnedAttribute, "returned"},
{ReturnsTwiceAttribute, "returns_twice"},
{SExtAttribute, "signext"},
{SafeStackAttribute, "safestack"},
{StackProtectAttribute, "ssp"},
{StackProtectReqAttribute, "sspreq"},
{StackProtectStrongAttribute, "sspstrong"},

View File

@ -277,6 +277,8 @@ uninstall-local:: uninstall-deplibs
build-deplibs: $(OutputLibs)
$(OcamlDir)/%.so: $(LibDir)/%.so
$(Verb) ln -sf $< $@
$(OcamlDir)/%.a: $(LibDir)/%.a
$(Verb) ln -sf $< $@

View File

@ -43,11 +43,11 @@ external run_static_dtors : llexecutionengine -> unit
= "llvm_ee_run_static_dtors"
external data_layout : llexecutionengine -> Llvm_target.DataLayout.t
= "llvm_ee_get_data_layout"
external add_global_mapping_ : Llvm.llvalue -> int64 -> llexecutionengine -> unit
external add_global_mapping_ : Llvm.llvalue -> nativeint -> llexecutionengine -> unit
= "llvm_ee_add_global_mapping"
external get_global_value_address_ : string -> llexecutionengine -> int64
external get_global_value_address_ : string -> llexecutionengine -> nativeint
= "llvm_ee_get_global_value_address"
external get_function_address_ : string -> llexecutionengine -> int64
external get_function_address_ : string -> llexecutionengine -> nativeint
= "llvm_ee_get_function_address"
let add_global_mapping llval ptr ee =
@ -55,14 +55,14 @@ let add_global_mapping llval ptr ee =
let get_global_value_address name typ ee =
let vptr = get_global_value_address_ name ee in
if Int64.to_int vptr <> 0 then
if Nativeint.to_int vptr <> 0 then
let open Ctypes in !@ (coerce (ptr void) (ptr typ) (ptr_of_raw_address vptr))
else
raise (Error ("Value " ^ name ^ " not found"))
let get_function_address name typ ee =
let fptr = get_function_address_ name ee in
if Int64.to_int fptr <> 0 then
if Nativeint.to_int fptr <> 0 then
let open Ctypes in coerce (ptr void) typ (ptr_of_raw_address fptr)
else
raise (Error ("Function " ^ name ^ " not found"))

View File

@ -371,14 +371,6 @@ class Relocation(LLVMObject):
self.expired = False
@CachedProperty
def address(self):
"""The address of this relocation, in long bytes."""
if self.expired:
raise Exception('Relocation instance has expired.')
return lib.LLVMGetRelocationAddress(self)
@CachedProperty
def offset(self):
"""The offset of this relocation, in long bytes."""
@ -498,9 +490,6 @@ def register_library(library):
library.LLVMGetSymbolSize.argtypes = [Symbol]
library.LLVMGetSymbolSize.restype = c_uint64
library.LLVMGetRelocationAddress.argtypes = [c_object_p]
library.LLVMGetRelocationAddress.restype = c_uint64
library.LLVMGetRelocationOffset.argtypes = [c_object_p]
library.LLVMGetRelocationOffset.restype = c_uint64

View File

@ -358,6 +358,10 @@ elseif (LLVM_NATIVE_ARCH MATCHES "hexagon")
set(LLVM_NATIVE_ARCH Hexagon)
elseif (LLVM_NATIVE_ARCH MATCHES "s390x")
set(LLVM_NATIVE_ARCH SystemZ)
elseif (LLVM_NATIVE_ARCH MATCHES "wasm32")
set(LLVM_NATIVE_ARCH WebAssembly)
elseif (LLVM_NATIVE_ARCH MATCHES "wasm64")
set(LLVM_NATIVE_ARCH WebAssembly)
else ()
message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}")
endif ()
@ -393,12 +397,10 @@ else ()
endif ()
if( MINGW )
set(HAVE_LIBIMAGEHLP 1)
set(HAVE_LIBPSAPI 1)
set(HAVE_LIBSHELL32 1)
# TODO: Check existence of libraries.
# include(CheckLibraryExists)
# CHECK_LIBRARY_EXISTS(imagehlp ??? . HAVE_LIBIMAGEHLP)
endif( MINGW )
if (NOT HAVE_STRTOLL)
@ -489,7 +491,7 @@ if (LLVM_ENABLE_DOXYGEN)
option(LLVM_DOXYGEN_EXTERNAL_SEARCH "Enable doxygen external search." OFF)
if (LLVM_DOXYGEN_EXTERNAL_SEARCH)
set(LLVM_DOXYGEN_SEARCHENGINE_URL "" CACHE STRING "URL to use for external searhc.")
set(LLVM_DOXYGEN_SEARCHENGINE_URL "" CACHE STRING "URL to use for external search.")
set(LLVM_DOXYGEN_SEARCH_MAPPINGS "" CACHE STRING "Doxygen Search Mappings")
endif()
endif()
@ -546,13 +548,13 @@ else()
if( OCAML_VERSION VERSION_LESS "4.00.0" )
message(STATUS "OCaml bindings disabled, need OCaml >=4.00.0.")
else()
find_ocamlfind_package(ctypes VERSION 0.3 OPTIONAL)
find_ocamlfind_package(ctypes VERSION 0.4 OPTIONAL)
if( HAVE_OCAML_CTYPES )
message(STATUS "OCaml bindings enabled.")
find_ocamlfind_package(oUnit VERSION 2 OPTIONAL)
set(LLVM_BINDINGS "${LLVM_BINDINGS} ocaml")
else()
message(STATUS "OCaml bindings disabled, need ctypes >=0.3.")
message(STATUS "OCaml bindings disabled, need ctypes >=0.4.")
endif()
endif()
endif()

View File

@ -1,4 +1,3 @@
include(LLVMParseArguments)
include(LLVMProcessSources)
include(LLVM-Config)
@ -84,25 +83,19 @@ function(add_llvm_symbol_exports target_name export_file)
DEPENDS ${export_file}
VERBATIM
COMMENT "Creating export file for ${target_name}")
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-M,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
else()
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
endif()
else()
set(native_export_file "${target_name}.def")
set(CAT "cat")
set(export_file_nativeslashes ${export_file})
if(WIN32 AND NOT CYGWIN AND NOT MSYS)
set(CAT "type")
# Convert ${export_file} to native format (backslashes) for "type"
# Does not use file(TO_NATIVE_PATH) as it doesn't create a native
# path but a build-system specific format (see CMake bug
# http://public.kitware.com/Bug/print_bug_page.php?bug_id=5939 )
string(REPLACE / \\ export_file_nativeslashes ${export_file})
endif()
add_custom_command(OUTPUT ${native_export_file}
COMMAND ${CMAKE_COMMAND} -E echo "EXPORTS" > ${native_export_file}
COMMAND ${CAT} ${export_file_nativeslashes} >> ${native_export_file}
COMMAND ${PYTHON_EXECUTABLE} -c "import sys;print(''.join(['EXPORTS\\n']+sys.stdin.readlines(),))"
< ${export_file} > ${native_export_file}
DEPENDS ${export_file}
VERBATIM
COMMENT "Creating export file for ${target_name}")
@ -164,7 +157,7 @@ function(add_link_opts target_name)
# Pass -O3 to the linker. This enabled different optimizations on different
# linkers.
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32))
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin|SunOS" OR WIN32))
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-O3")
endif()
@ -182,6 +175,9 @@ function(add_link_opts target_name)
# ld64's implementation of -dead_strip breaks tools that use plugins.
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-dead_strip")
elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-z -Wl,discard-unused=sections")
elseif(NOT WIN32 AND NOT LLVM_LINKER_IS_GOLD)
# Object files are compiled with -ffunction-data-sections.
# Versions of bfd ld < 2.23.1 have a bug in --gc-sections that breaks
@ -286,6 +282,8 @@ function(set_windows_version_resource_properties name resource_file)
set(ARG_PRODUCT_NAME "LLVM")
endif()
set_property(SOURCE ${resource_file}
PROPERTY COMPILE_FLAGS /nologo)
set_property(SOURCE ${resource_file}
PROPERTY COMPILE_DEFINITIONS
"RC_VERSION_FIELD_1=${ARG_VERSION_MAJOR}"
@ -494,11 +492,17 @@ macro(add_llvm_library name)
else()
llvm_add_library(${name} ${ARGN})
endif()
set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} )
# The gtest libraries should not be installed or exported as a target
if ("${name}" STREQUAL gtest OR "${name}" STREQUAL gtest_main)
set(_is_gtest TRUE)
else()
set(_is_gtest FALSE)
set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} )
endif()
if( EXCLUDE_FROM_ALL )
set_target_properties( ${name} PROPERTIES EXCLUDE_FROM_ALL ON)
else()
elseif(NOT _is_gtest)
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "LTO")
if(ARG_SHARED OR BUILD_SHARED_LIBS)
if(WIN32 OR CYGWIN)
@ -672,6 +676,13 @@ macro(add_llvm_target target_name)
set( CURRENT_LLVM_TARGET LLVM${target_name} )
endmacro(add_llvm_target)
function(canonicalize_tool_name name output)
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" nameStrip ${name})
string(REPLACE "-" "_" nameUNDERSCORE ${nameStrip})
string(TOUPPER ${nameUNDERSCORE} nameUPPER)
set(${output} "${nameUPPER}" PARENT_SCOPE)
endfunction(canonicalize_tool_name)
# Add external project that may want to be built as part of llvm such as Clang,
# lld, and Polly. This adds two options. One for the source directory of the
# project, which defaults to ${CMAKE_CURRENT_SOURCE_DIR}/${name}. Another to
@ -682,38 +693,68 @@ macro(add_llvm_external_project name)
if("${add_llvm_external_dir}" STREQUAL "")
set(add_llvm_external_dir ${name})
endif()
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}")
string(REPLACE "-" "_" nameUNDERSCORE ${name})
string(TOUPPER ${nameUNDERSCORE} nameUPPER)
set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}"
CACHE PATH "Path to ${name} source directory")
if (NOT ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} STREQUAL ""
AND EXISTS ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}/CMakeLists.txt)
option(LLVM_EXTERNAL_${nameUPPER}_BUILD
"Whether to build ${name} as part of LLVM" ON)
if (LLVM_EXTERNAL_${nameUPPER}_BUILD)
canonicalize_tool_name(${name} nameUPPER)
if(NOT DEFINED LLVM_TOOL_${nameUPPER}_BUILD)
option(LLVM_TOOL_${nameUPPER}_BUILD
"Whether to build ${name} as part of LLVM" On)
endif()
if (LLVM_TOOL_${nameUPPER}_BUILD)
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}/CMakeLists.txt)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir} ${add_llvm_external_dir})
set(LLVM_TOOL_${nameUPPER}_BUILD Off)
elseif(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR)
set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR
"${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}"
CACHE PATH "Path to ${name} source directory")
mark_as_advanced(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR)
add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir})
set(LLVM_TOOL_${nameUPPER}_BUILD Off)
endif()
endif()
endmacro(add_llvm_external_project)
macro(add_llvm_tool_subdirectory name)
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}")
add_subdirectory(${name})
add_llvm_external_project(${name})
endmacro(add_llvm_tool_subdirectory)
macro(ignore_llvm_tool_subdirectory name)
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}")
endmacro(ignore_llvm_tool_subdirectory)
function(get_project_name_from_src_var var output)
string(REGEX MATCH "LLVM_EXTERNAL_(.*)_SOURCE_DIR"
MACHED_TOOL "${var}")
if(MACHED_TOOL)
set(${output} ${CMAKE_MATCH_1} PARENT_SCOPE)
else()
set(${output} PARENT_SCOPE)
endif()
endfunction()
function(add_llvm_implicit_external_projects)
function(create_llvm_tool_options)
file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*")
foreach(dir ${sub-dirs})
if(IS_DIRECTORY "${dir}" AND EXISTS "${dir}/CMakeLists.txt")
canonicalize_tool_name(${dir} name)
option(LLVM_TOOL_${name}_BUILD
"Whether to build ${name} as part of LLVM" On)
mark_as_advanced(LLVM_TOOL_${name}_BUILD)
endif()
endforeach()
get_cmake_property(variableNames VARIABLES)
foreach (variableName ${variableNames})
get_project_name_from_src_var(${variableName} projectName)
if(projectName)
option(LLVM_TOOL_${projectName}_BUILD
"Whether to build ${name} as part of LLVM" On)
mark_as_advanced(LLVM_TOOL_${name}_BUILD)
endif()
endforeach()
endfunction(create_llvm_tool_options)
function(add_llvm_implicit_projects)
set(list_of_implicit_subdirs "")
file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*")
foreach(dir ${sub-dirs})
if(IS_DIRECTORY "${dir}")
list(FIND LLVM_IMPLICIT_PROJECT_IGNORE "${dir}" tool_subdir_ignore)
if( tool_subdir_ignore EQUAL -1
AND EXISTS "${dir}/CMakeLists.txt")
if(IS_DIRECTORY "${dir}" AND EXISTS "${dir}/CMakeLists.txt")
canonicalize_tool_name(${dir} name)
if (LLVM_TOOL_${name}_BUILD)
get_filename_component(fn "${dir}" NAME)
list(APPEND list_of_implicit_subdirs "${fn}")
endif()
@ -723,7 +764,7 @@ function(add_llvm_implicit_external_projects)
foreach(external_proj ${list_of_implicit_subdirs})
add_llvm_external_project("${external_proj}")
endforeach()
endfunction(add_llvm_implicit_external_projects)
endfunction(add_llvm_implicit_projects)
# Generic support for adding a unittest.
function(add_unittest test_suite test_name)
@ -774,7 +815,7 @@ function(llvm_add_go_executable binary pkgpath)
endforeach(d)
set(ldflags "${CMAKE_EXE_LINKER_FLAGS}")
add_custom_command(OUTPUT ${binpath}
COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}"
COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "go=${GO_EXECUTABLE}" "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}"
${ARG_GOFLAGS} build -o ${binpath} ${pkgpath}
DEPENDS llvm-config ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX}
${llvmlibs} ${ARG_DEPENDS}
@ -845,7 +886,7 @@ endfunction()
# A raw function to create a lit target. This is used to implement the testuite
# management functions.
function(add_lit_target target comment)
parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN})
cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
set(LIT_ARGS "${ARG_ARGS} ${LLVM_LIT_ARGS}")
separate_arguments(LIT_ARGS)
if (NOT CMAKE_CFG_INTDIR STREQUAL ".")
@ -860,9 +901,9 @@ function(add_lit_target target comment)
foreach(param ${ARG_PARAMS})
list(APPEND LIT_COMMAND --param ${param})
endforeach()
if (ARG_DEFAULT_ARGS)
if (ARG_UNPARSED_ARGUMENTS)
add_custom_target(${target}
COMMAND ${LIT_COMMAND} ${ARG_DEFAULT_ARGS}
COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS}
COMMENT "${comment}"
${cmake_3_2_USES_TERMINAL}
)
@ -881,12 +922,12 @@ endfunction()
# A function to add a set of lit test suites to be driven through 'check-*' targets.
function(add_lit_testsuite target comment)
parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN})
cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
# EXCLUDE_FROM_ALL excludes the test ${target} out of check-all.
if(NOT EXCLUDE_FROM_ALL)
# Register the testsuites, params and depends for the global check rule.
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_TESTSUITES ${ARG_DEFAULT_ARGS})
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_TESTSUITES ${ARG_UNPARSED_ARGUMENTS})
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_PARAMS ${ARG_PARAMS})
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_DEPENDS ${ARG_DEPENDS})
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_EXTRA_ARGS ${ARG_ARGS})
@ -894,7 +935,7 @@ function(add_lit_testsuite target comment)
# Produce a specific suffixed check rule.
add_lit_target(${target} ${comment}
${ARG_DEFAULT_ARGS}
${ARG_UNPARSED_ARGUMENTS}
PARAMS ${ARG_PARAMS}
DEPENDS ${ARG_DEPENDS}
ARGS ${ARG_ARGS}
@ -903,7 +944,7 @@ endfunction()
function(add_lit_testsuites project directory)
if (NOT CMAKE_CONFIGURATION_TYPES)
parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN})
cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
file(GLOB_RECURSE litCfg ${directory}/lit*.cfg)
set(lit_suites)
foreach(f ${litCfg})

View File

@ -2,15 +2,45 @@
INCLUDE(CheckCXXSourceCompiles)
check_function_exists(__atomic_fetch_add_4 HAVE___ATOMIC_FETCH_ADD_4)
if( NOT HAVE___ATOMIC_FETCH_ADD_4 )
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
set(HAVE_LIBATOMIC False)
if( HAVE_LIBATOMIC )
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
# Sometimes linking against libatomic is required for atomic ops, if
# the platform doesn't support lock-free atomics.
function(check_working_cxx_atomics varname)
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
CHECK_CXX_SOURCE_COMPILES("
#include <atomic>
std::atomic<int> x;
int main() {
return x;
}
" ${varname})
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
endfunction(check_working_cxx_atomics)
# This isn't necessary on MSVC, so avoid command-line switch annoyance
# by only running on GCC-like hosts.
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
# First check if atomics work without the library.
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
# If not, check if the library exists, and atomics work with it.
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
if( HAVE_LIBATOMIC )
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
message(FATAL_ERROR "Host compiler must support std::atomic!")
endif()
else()
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
endif()
endif()
endif()
## TODO: This define is only used for the legacy atomic operations in
## llvm's Atomic.h, which should be replaced. Other code simply
## assumes C++11 <atomic> works.
CHECK_CXX_SOURCE_COMPILES("
#ifdef _MSC_VER
#include <Intrin.h> /* Workaround for PR19898. */

View File

@ -131,7 +131,7 @@ endif()
# Pass -Wl,-z,defs. This makes sure all symbols are defined. Otherwise a DSO
# build might work on ELF but fail on MachO/COFF.
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR CYGWIN OR
${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") AND
NOT LLVM_USE_SANITIZER)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs")
@ -166,6 +166,7 @@ function(add_flag_or_print_warning flag name)
message(STATUS "Building with ${flag}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}" PARENT_SCOPE)
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${flag}" PARENT_SCOPE)
else()
message(WARNING "${flag} is not supported.")
endif()
@ -307,10 +308,12 @@ if( MSVC )
-wd4611 # Suppress 'interaction between '_setjmp' and C++ object destruction is non-portable'
-wd4805 # Suppress 'unsafe mix of type <type> and type <type> in operation'
-wd4204 # Suppress 'nonstandard extension used : non-constant aggregate initializer'
-wd4577 # Suppress 'noexcept used with no exception handling mode specified; termination on exception is not guaranteed'
-wd4091 # Suppress 'typedef: ignored on left of '' when no variable is declared'
# Idelly, we'd like this warning to be enabled, but MSVC 2013 doesn't
# Ideally, we'd like this warning to be enabled, but MSVC 2013 doesn't
# support the 'aligned' attribute in the way that clang sources requires (for
# any code that uses the LLVM_ALIGNAS marco), so this is must be disabled to
# any code that uses the LLVM_ALIGNAS macro), so this is must be disabled to
# avoid unwanted alignment warnings.
# When we switch to requiring a version of MSVC that supports the 'alignas'
# specifier (MSVC 2015?) this warning can be re-enabled.

View File

@ -1,80 +0,0 @@
# Copied from http://www.itk.org/Wiki/CMakeMacroParseArguments under
# http://creativecommons.org/licenses/by/2.5/.
#
# The PARSE_ARGUMENTS macro will take the arguments of another macro and define
# several variables. The first argument to PARSE_ARGUMENTS is a prefix to put on
# all variables it creates. The second argument is a list of names, and the
# third argument is a list of options. Both of these lists should be quoted. The
# rest of PARSE_ARGUMENTS are arguments from another macro to be parsed.
#
# PARSE_ARGUMENTS(prefix arg_names options arg1 arg2...)
#
# For each item in options, PARSE_ARGUMENTS will create a variable with that
# name, prefixed with prefix_. So, for example, if prefix is MY_MACRO and
# options is OPTION1;OPTION2, then PARSE_ARGUMENTS will create the variables
# MY_MACRO_OPTION1 and MY_MACRO_OPTION2. These variables will be set to true if
# the option exists in the command line or false otherwise.
#
#For each item in arg_names, PARSE_ARGUMENTS will create a variable with that
#name, prefixed with prefix_. Each variable will be filled with the arguments
#that occur after the given arg_name is encountered up to the next arg_name or
#the end of the arguments. All options are removed from these
#lists. PARSE_ARGUMENTS also creates a prefix_DEFAULT_ARGS variable containing
#the list of all arguments up to the first arg_name encountered.
#
#Here is a simple, albeit impractical, example of using PARSE_ARGUMENTS that
#demonstrates its behavior.
#
# SET(arguments
# hello OPTION3 world
# LIST3 foo bar
# OPTION2
# LIST1 fuz baz
# )
#
# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "OPTION1;OPTION2;OPTION3" ${arguments})
#
# PARSE_ARGUMENTS creates 7 variables and sets them as follows:
# ARG_DEFAULT_ARGS: hello;world
# ARG_LIST1: fuz;baz
# ARG_LIST2:
# ARG_LIST3: foo;bar
# ARG_OPTION1: FALSE
# ARG_OPTION2: TRUE
# ARG_OPTION3: TRUE
#
# If you don't have any options, use an empty string in its place.
# PARSE_ARGUMENTS(ARG "LIST1;LIST2;LIST3" "" ${arguments})
# Likewise if you have no lists.
# PARSE_ARGUMENTS(ARG "" "OPTION1;OPTION2;OPTION3" ${arguments})
MACRO(PARSE_ARGUMENTS prefix arg_names option_names)
SET(DEFAULT_ARGS)
FOREACH(arg_name ${arg_names})
SET(${prefix}_${arg_name})
ENDFOREACH(arg_name)
FOREACH(option ${option_names})
SET(${prefix}_${option} FALSE)
ENDFOREACH(option)
SET(current_arg_name DEFAULT_ARGS)
SET(current_arg_list)
FOREACH(arg ${ARGN})
SET(larg_names ${arg_names})
LIST(FIND larg_names "${arg}" is_arg_name)
IF (is_arg_name GREATER -1)
SET(${prefix}_${current_arg_name} ${current_arg_list})
SET(current_arg_name ${arg})
SET(current_arg_list)
ELSE (is_arg_name GREATER -1)
SET(loption_names ${option_names})
LIST(FIND loption_names "${arg}" is_option)
IF (is_option GREATER -1)
SET(${prefix}_${arg} TRUE)
ELSE (is_option GREATER -1)
SET(current_arg_list ${current_arg_list} ${arg})
ENDIF (is_option GREATER -1)
ENDIF (is_arg_name GREATER -1)
ENDFOREACH(arg)
SET(${prefix}_${current_arg_name} ${current_arg_list})
ENDMACRO(PARSE_ARGUMENTS)

View File

@ -47,6 +47,12 @@ ifeq ($(LLVM_LIBS_TO_EXPORT),Error)
$(error llvm-config --libs failed)
endif
# Strip out gtest and gtest_main from LLVM_LIBS_TO_EXPORT, these are not
# installed and won't be available from the install tree.
# FIXME: If we used llvm-config from the install tree this wouldn't be
# necessary.
LLVM_LIBS_TO_EXPORT := $(filter-out gtest gtest_main,$(LLVM_LIBS_TO_EXPORT))
ifndef LLVM_LIBS_TO_EXPORT
$(error LLVM_LIBS_TO_EXPORT cannot be empty)
endif
@ -54,11 +60,27 @@ endif
OBJMODS := LLVMConfig.cmake LLVMConfigVersion.cmake LLVMExports.cmake
LLVM_CONFIG_CODE := \
\# Compute the CMake directory from the LLVMConfig.cmake file location.\n\
get_filename_component(_LLVM_CMAKE_DIR "$${CMAKE_CURRENT_LIST_FILE}" PATH)\n\
\# Compute the installation prefix from the LLVMConfig.cmake file location.\n\
get_filename_component(LLVM_INSTALL_PREFIX "$${CMAKE_CURRENT_LIST_FILE}" PATH)\n
# Compute number of levels (typically 3 - ``share/llvm/cmake/``) to PROJ_prefix
# from PROJ_cmake, then emit the appropriate number of calls to
# get_filename_components(). Note this assumes there are no spaces in the
# cmake_path_suffix variable.
cmake_path_suffix := $(subst $(PROJ_prefix),,$(subst $(DESTDIR),,$(PROJ_cmake)))
cmake_path_dirs := $(subst /, ,$(cmake_path_suffix))
LLVM_CONFIG_CODE += $(foreach __not_used,$(cmake_path_dirs),get_filename_component(LLVM_INSTALL_PREFIX "$${LLVM_INSTALL_PREFIX}" PATH)\n)
LLVM_CONFIG_CODE += set(_LLVM_LIBRARY_DIR "$${LLVM_INSTALL_PREFIX}\/lib")
$(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeFrag)
$(Echo) 'Generating LLVM CMake package config file'
$(Verb) ( \
cat $< | sed \
-e 's/@LLVM_CONFIG_CODE@/set(LLVM_INSTALL_PREFIX "'"$(subst /,\/,$(PROJ_prefix))"'")/' \
-e 's/@LLVM_CONFIG_CODE@/$(LLVM_CONFIG_CODE)/' \
-e 's/@LLVM_VERSION_MAJOR@/'"$(LLVM_VERSION_MAJOR)"'/' \
-e 's/@LLVM_VERSION_MINOR@/'"$(LLVM_VERSION_MINOR)"'/' \
-e 's/@LLVM_VERSION_PATCH@/'"$(LLVM_VERSION_PATCH)"'/' \
@ -81,17 +103,20 @@ $(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeF
-e 's/@LLVM_ON_UNIX@/'"$(LLVM_ON_UNIX)"'/' \
-e 's/@LLVM_ON_WIN32@/'"$(LLVM_ON_WIN32)"'/' \
-e 's/@LLVM_LIBDIR_SUFFIX@//' \
-e 's/@LLVM_CONFIG_INCLUDE_DIRS@/'"$(subst /,\/,$(PROJ_includedir))"'/' \
-e 's/@LLVM_CONFIG_LIBRARY_DIRS@/'"$(subst /,\/,$(PROJ_libdir))"'/' \
-e 's/@LLVM_CONFIG_CMAKE_DIR@/'"$(subst /,\/,$(PROJ_cmake))"'/' \
-e 's/@LLVM_CONFIG_TOOLS_BINARY_DIR@/'"$(subst /,\/,$(PROJ_bindir))"'/' \
-e 's#@LLVM_CONFIG_INCLUDE_DIRS@#$${LLVM_INSTALL_PREFIX}/include#' \
-e 's#@LLVM_CONFIG_LIBRARY_DIRS@#$${_LLVM_LIBRARY_DIR}#' \
-e 's#@LLVM_CONFIG_CMAKE_DIR@#$${_LLVM_CMAKE_DIR}#' \
-e 's#@LLVM_CONFIG_TOOLS_BINARY_DIR@#$${LLVM_INSTALL_PREFIX}/bin#' \
-e 's/@LLVM_CONFIG_EXPORTS_FILE@/$${LLVM_CMAKE_DIR}\/LLVMExports.cmake/' \
-e 's/@all_llvm_lib_deps@//' \
&& \
grep '^set_property.*LLVMBUILD_LIB_DEPS_' "$(LLVMBuildCMakeFrag)" \
( grep '^set_property.*LLVMBUILD_LIB_DEPS_' "$(LLVMBuildCMakeFrag)" | \
grep -v LLVMBUILD_LIB_DEPS_gtest ) && \
echo 'unset(_LLVM_CMAKE_DIR)' && \
echo 'unset(_LLVM_LIBRARY_DIR)' \
) > $@
$(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in
$(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in Makefile
$(Echo) 'Generating LLVM CMake package version file'
$(Verb) cat $< | sed \
-e 's/@PACKAGE_VERSION@/'"$(LLVMVersion)"'/' \
@ -100,13 +125,13 @@ $(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in
-e 's/@LLVM_VERSION_PATCH@/'"$(LLVM_VERSION_PATCH)"'/' \
> $@
$(PROJ_OBJ_DIR)/LLVMExports.cmake: $(LLVMBuildCMakeExportsFrag)
$(PROJ_OBJ_DIR)/LLVMExports.cmake: $(LLVMBuildCMakeExportsFrag) Makefile
$(Echo) 'Generating LLVM CMake target exports file'
$(Verb) ( \
echo '# LLVM CMake target exports. Do not include directly.' && \
for lib in $(LLVM_LIBS_TO_EXPORT); do \
echo 'add_library('"$$lib"' STATIC IMPORTED)' && \
echo 'set_property(TARGET '"$$lib"' PROPERTY IMPORTED_LOCATION "'"$(PROJ_libdir)/lib$$lib.a"'")' ; \
echo 'set_property(TARGET '"$$lib"' PROPERTY IMPORTED_LOCATION "$${_LLVM_LIBRARY_DIR}/'lib$$lib.a'")' ; \
done && \
cat "$(LLVMBuildCMakeExportsFrag)" && \
echo 'set_property(TARGET LLVMSupport APPEND PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES '"$(subst -l,,$(LIBS))"')' \

130
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.60 for LLVM 3.7.0svn.
# Generated by GNU Autoconf 2.60 for LLVM 3.8.0svn.
#
# Report bugs to <http://llvm.org/bugs/>.
#
@ -561,8 +561,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package.
PACKAGE_NAME='LLVM'
PACKAGE_TARNAME='llvm'
PACKAGE_VERSION='3.7.0svn'
PACKAGE_STRING='LLVM 3.7.0svn'
PACKAGE_VERSION='3.8.0svn'
PACKAGE_STRING='LLVM 3.8.0svn'
PACKAGE_BUGREPORT='http://llvm.org/bugs/'
ac_unique_file="lib/IR/Module.cpp"
@ -1333,7 +1333,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures LLVM 3.7.0svn to adapt to many kinds of systems.
\`configure' configures LLVM 3.8.0svn to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1399,7 +1399,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of LLVM 3.7.0svn:";;
short | recursive ) echo "Configuration of LLVM 3.8.0svn:";;
esac
cat <<\_ACEOF
@ -1463,7 +1463,7 @@ Optional Features:
target1,target2,... Valid targets are: host, x86,
x86_64, sparc, powerpc, arm64, arm, aarch64, mips,
hexagon, xcore, msp430, nvptx, systemz, r600, bpf,
and cpp (default=all)
wasm, and cpp (default=all)
--enable-experimental-targets
Build experimental host targets: disable or
target1,target2,... (default=disable)
@ -1583,7 +1583,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
LLVM configure 3.7.0svn
LLVM configure 3.8.0svn
generated by GNU Autoconf 2.60
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
@ -1599,7 +1599,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by LLVM $as_me 3.7.0svn, which was
It was created by LLVM $as_me 3.8.0svn, which was
generated by GNU Autoconf 2.60. Invocation command line was
$ $0 $@
@ -1954,7 +1954,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
LLVM_VERSION_MAJOR=3
LLVM_VERSION_MINOR=7
LLVM_VERSION_MINOR=8
LLVM_VERSION_PATCH=0
LLVM_VERSION_SUFFIX=svn
@ -2033,24 +2033,9 @@ echo "$as_me: error: Already configured in ${srcdir}" >&2;}
fi
if test ${srcdir} == "." ; then
{ echo "$as_me:$LINENO: WARNING: **************************************************************************************" >&5
echo "$as_me: WARNING: **************************************************************************************" >&2;}
{ echo "$as_me:$LINENO: WARNING: * *" >&5
echo "$as_me: WARNING: * *" >&2;}
{ echo "$as_me:$LINENO: WARNING: * WARNING *" >&5
echo "$as_me: WARNING: * WARNING *" >&2;}
{ echo "$as_me:$LINENO: WARNING: * *" >&5
echo "$as_me: WARNING: * *" >&2;}
{ echo "$as_me:$LINENO: WARNING: * In-source builds are deprecated. *" >&5
echo "$as_me: WARNING: * In-source builds are deprecated. *" >&2;}
{ echo "$as_me:$LINENO: WARNING: * *" >&5
echo "$as_me: WARNING: * *" >&2;}
{ echo "$as_me:$LINENO: WARNING: * Please configure from a separate build directory! *" >&5
echo "$as_me: WARNING: * Please configure from a separate build directory! *" >&2;}
{ echo "$as_me:$LINENO: WARNING: * *" >&5
echo "$as_me: WARNING: * *" >&2;}
{ echo "$as_me:$LINENO: WARNING: **************************************************************************************" >&5
echo "$as_me: WARNING: **************************************************************************************" >&2;}
{ { echo "$as_me:$LINENO: error: In-source builds are not allowed. Please configure from a separate build directory!" >&5
echo "$as_me: error: In-source builds are not allowed. Please configure from a separate build directory!" >&2;}
{ (exit 1); exit 1; }; }
fi
: ${CFLAGS=}
@ -4207,6 +4192,7 @@ else
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
nvptx-*) llvm_cv_target_arch="NVPTX" ;;
s390x-*) llvm_cv_target_arch="SystemZ" ;;
wasm*-*) llvm_cv_target_arch="WebAssembly" ;;
*) llvm_cv_target_arch="Unknown" ;;
esac
fi
@ -4243,6 +4229,7 @@ case $host in
msp430-*) host_arch="MSP430" ;;
hexagon-*) host_arch="Hexagon" ;;
s390x-*) host_arch="SystemZ" ;;
wasm*-*) host_arch="WebAssembly" ;;
*) host_arch="Unknown" ;;
esac
@ -5169,6 +5156,8 @@ else
NVPTX) TARGET_HAS_JIT=0
;;
SystemZ) TARGET_HAS_JIT=1
;;
WebAssembly) TARGET_HAS_JIT=0
;;
*) TARGET_HAS_JIT=0
;;
@ -5667,6 +5656,7 @@ case "$enableval" in
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
r600) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
wasm) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;;
host) case "$llvm_cv_target_arch" in
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
@ -5680,6 +5670,7 @@ case "$enableval" in
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
WebAssembly) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;;
*) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5
echo "$as_me: error: Can not set target to build" >&2;}
{ (exit 1); exit 1; }; } ;;
@ -8733,6 +8724,87 @@ _ACEOF
fi
{ echo "$as_me:$LINENO: checking for main in -lole32" >&5
echo $ECHO_N "checking for main in -lole32... $ECHO_C" >&6; }
if test "${ac_cv_lib_ole32_main+set}" = set; then
echo $ECHO_N "(cached) $ECHO_C" >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-lole32 $LIBS"
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
int
main ()
{
return main ();
;
return 0;
}
_ACEOF
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } &&
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; } &&
{ ac_try='test -s conftest$ac_exeext'
{ (case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
(eval "$ac_try") 2>&5
ac_status=$?
echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); }; }; then
ac_cv_lib_ole32_main=yes
else
echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
ac_cv_lib_ole32_main=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ echo "$as_me:$LINENO: result: $ac_cv_lib_ole32_main" >&5
echo "${ECHO_T}$ac_cv_lib_ole32_main" >&6; }
if test $ac_cv_lib_ole32_main = yes; then
cat >>confdefs.h <<_ACEOF
#define HAVE_LIBOLE32 1
_ACEOF
LIBS="-lole32 $LIBS"
fi
{ echo "$as_me:$LINENO: checking for main in -lpsapi" >&5
echo $ECHO_N "checking for main in -lpsapi... $ECHO_C" >&6; }
if test "${ac_cv_lib_psapi_main+set}" = set; then
@ -18538,7 +18610,7 @@ exec 6>&1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by LLVM $as_me 3.7.0svn, which was
This file was extended by LLVM $as_me 3.8.0svn, which was
generated by GNU Autoconf 2.60. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@ -18591,7 +18663,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF
cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\
LLVM config.status 3.7.0svn
LLVM config.status 3.8.0svn
configured by $0, generated by GNU Autoconf 2.60,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"

View File

@ -92,3 +92,86 @@ strings:
v_mul_i32_i24 v1, v2, v3
v_mul_i32_i24_e32 v1, v2, v3
v_mul_i32_i24_e64 v1, v2, v3
Assembler Directives
--------------------
.hsa_code_object_version major, minor
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*major* and *minor* are integers that specify the version of the HSA code
object that will be generated by the assembler. This value will be stored
in an entry of the .note section.
.hsa_code_object_isa [major, minor, stepping, vendor, arch]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
*major*, *minor*, and *stepping* are all integers that describe the instruction
set architecture (ISA) version of the assembly program.
*vendor* and *arch* are quoted strings. *vendor* should always be equal to
"AMD" and *arch* should always be equal to "AMDGPU".
If no arguments are specified, then the assembler will derive the ISA version,
*vendor*, and *arch* from the value of the -mcpu option that is passed to the
assembler.
ISA version, *vendor*, and *arch* will all be stored in a single entry of the
.note section.
.amd_kernel_code_t
^^^^^^^^^^^^^^^^^^
This directive marks the beginning of a list of key / value pairs that are used
to specify the amd_kernel_code_t object that will be emitted by the assembler.
The list must be terminated by the *.end_amd_kernel_code_t* directive. For
any amd_kernel_code_t values that are unspecified a default value will be
used. The default value for all keys is 0, with the following exceptions:
- *kernel_code_version_major* defaults to 1.
- *machine_kind* defaults to 1.
- *machine_version_major*, *machine_version_minor*, and
*machine_version_stepping* are derived from the value of the -mcpu option
that is passed to the assembler.
- *kernel_code_entry_byte_offset* defaults to 256.
- *wavefront_size* defaults to 6.
- *kernarg_segment_alignment*, *group_segment_alignment*, and
*private_segment_alignment* default to 4. Note that alignments are specified
as a power of two, so a value of **n** means an alignment of 2^ **n**.
The *.amd_kernel_code_t* directive must be placed immediately after the
function label and before any instructions.
For a full list of amd_kernel_code_t keys, see the examples in
test/CodeGen/AMDGPU/hsa.s. For an explanation of the meanings of the different
keys, see the comments in lib/Target/AMDGPU/AmdKernelCodeT.h
Here is an example of a minimal amd_kernel_code_t specification:
.. code-block:: nasm
.hsa_code_object_version 1,0
.hsa_code_object_isa
.text
hello_world:
.amd_kernel_code_t
enable_sgpr_kernarg_segment_ptr = 1
is_ptr64 = 1
compute_pgm_rsrc1_vgprs = 0
compute_pgm_rsrc1_sgprs = 0
compute_pgm_rsrc2_user_sgpr = 2
kernarg_segment_byte_size = 8
wavefront_sgpr_count = 2
workitem_vgpr_count = 3
.end_amd_kernel_code_t
s_load_dwordx2 s[0:1], s[0:1] 0x0
v_mov_b32 v0, 3.14159
s_waitcnt lgkmcnt(0)
v_mov_b32 v1, s0
v_mov_b32 v2, s1
flat_store_dword v0, v[1:2]
s_endpgm

View File

@ -286,8 +286,8 @@ Mod/Ref result, simply return whatever the superclass computes. For example:
.. code-block:: c++
AliasAnalysis::AliasResult alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) {
AliasResult alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) {
if (...)
return NoAlias;
...

View File

@ -741,7 +741,7 @@ global variable. The operand fields are:
MODULE_CODE_FUNCTION Record
^^^^^^^^^^^^^^^^^^^^^^^^^^^
``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata]``
``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata, personalityfn]``
The ``FUNCTION`` record (code 8) marks the declaration or definition of a
function. The operand fields are:
@ -795,6 +795,8 @@ function. The operand fields are:
* *prefixdata*: If non-zero, the value index of the prefix data for this function,
plus 1.
* *personalityfn*: If non-zero, the value index of the personality function for this function,
plus 1.
MODULE_CODE_ALIAS Record
^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -327,8 +327,8 @@ LLVM-specific variables
**LLVM_USE_SANITIZER**:STRING
Define the sanitizer used to build LLVM binaries and tests. Possible values
are ``Address``, ``Memory``, ``MemoryWithOrigins`` and ``Undefined``.
Defaults to empty string.
are ``Address``, ``Memory``, ``MemoryWithOrigins``, ``Undefined``, ``Thread``,
and ``Address;Undefined``. Defaults to empty string.
**LLVM_PARALLEL_COMPILE_JOBS**:STRING
Define the maximum number of concurrent compilation jobs.

View File

@ -138,7 +138,9 @@ if( NOT uses_ocaml LESS 0 )
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html
COMMAND ${OCAMLFIND} ocamldoc -d ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html
-sort -colorize-code -html ${odoc_files})
-sort -colorize-code -html ${odoc_files}
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/_ocamldoc/style.css
${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html)
add_dependencies(ocaml_doc ${doc_targets})

View File

@ -749,7 +749,7 @@ The SelectionDAG is a Directed-Acyclic-Graph whose nodes are instances of the
``SDNode`` class. The primary payload of the ``SDNode`` is its operation code
(Opcode) that indicates what operation the node performs and the operands to the
operation. The various operation node types are described at the top of the
``include/llvm/CodeGen/SelectionDAGNodes.h`` file.
``include/llvm/CodeGen/ISDOpcodes.h`` file.
Although most operations define a single value, each node in the graph may
define multiple values. For example, a combined div/rem operation will define
@ -829,7 +829,7 @@ One great way to visualize what is going on here is to take advantage of a few
LLC command line options. The following options pop up a window displaying the
SelectionDAG at specific times (if you only get errors printed to the console
while using this, you probably `need to configure your
system <ProgrammersManual.html#ViewGraph>`_ to add support for it).
system <ProgrammersManual.html#viewing-graphs-while-debugging-code>`_ to add support for it).
* ``-view-dag-combine1-dags`` displays the DAG after being built, before the
first optimization pass.

View File

@ -21,6 +21,7 @@ Basic Commands
lli
llvm-link
llvm-ar
llvm-lib
llvm-nm
llvm-config
llvm-diff

View File

@ -161,7 +161,7 @@ ADDITIONAL OPTIONS
.. option:: --show-tests
List all of the the discovered tests and exit.
List all of the discovered tests and exit.
EXIT STATUS
-----------

View File

@ -1,172 +1,127 @@
lli - directly execute programs from LLVM bitcode
=================================================
SYNOPSIS
--------
**lli** [*options*] [*filename*] [*program args*]
:program:`lli` [*options*] [*filename*] [*program args*]
DESCRIPTION
-----------
:program:`lli` directly executes programs in LLVM bitcode format. It takes a program
in LLVM bitcode format and executes it using a just-in-time compiler or an
interpreter.
**lli** directly executes programs in LLVM bitcode format. It takes a program
in LLVM bitcode format and executes it using a just-in-time compiler, if one is
available for the current architecture, or an interpreter. **lli** takes all of
the same code generator options as llc|llc, but they are only effective when
**lli** is using the just-in-time compiler.
:program:`lli` is *not* an emulator. It will not execute IR of different architectures
and it can only interpret (or JIT-compile) for the host architecture.
If *filename* is not specified, then **lli** reads the LLVM bitcode for the
The JIT compiler takes the same arguments as other tools, like :program:`llc`,
but they don't necessarily work for the interpreter.
If `filename` is not specified, then :program:`lli` reads the LLVM bitcode for the
program from standard input.
The optional *args* specified on the command line are passed to the program as
arguments.
GENERAL OPTIONS
---------------
**-fake-argv0**\ =\ *executable*
.. option:: -fake-argv0=executable
Override the ``argv[0]`` value passed into the executing program.
**-force-interpreter**\ =\ *{false,true}*
.. option:: -force-interpreter={false,true}
If set to true, use the interpreter even if a just-in-time compiler is available
for this architecture. Defaults to false.
**-help**
.. option:: -help
Print a summary of command line options.
.. option:: -load=pluginfilename
**-load**\ =\ *pluginfilename*
Causes **lli** to load the plugin (shared object) named *pluginfilename* and use
Causes :program:`lli` to load the plugin (shared object) named *pluginfilename* and use
it for optimization.
**-stats**
.. option:: -stats
Print statistics from the code-generation passes. This is only meaningful for
the just-in-time compiler, at present.
**-time-passes**
.. option:: -time-passes
Record the amount of time needed for each code-generation pass and print it to
standard error.
.. option:: -version
**-version**
Print out the version of **lli** and exit without doing anything else.
Print out the version of :program:`lli` and exit without doing anything else.
TARGET OPTIONS
--------------
**-mtriple**\ =\ *target triple*
.. option:: -mtriple=target triple
Override the target triple specified in the input bitcode file with the
specified string. This may result in a crash if you pick an
architecture which is not compatible with the current system.
**-march**\ =\ *arch*
.. option:: -march=arch
Specify the architecture for which to generate assembly, overriding the target
encoded in the bitcode file. See the output of **llc -help** for a list of
valid architectures. By default this is inferred from the target triple or
autodetected to the current architecture.
**-mcpu**\ =\ *cpuname*
.. option:: -mcpu=cpuname
Specify a specific chip in the current architecture to generate code for.
By default this is inferred from the target triple and autodetected to
the current architecture. For a list of available CPUs, use:
**llvm-as < /dev/null | llc -march=xyz -mcpu=help**
**-mattr**\ =\ *a1,+a2,-a3,...*
.. option:: -mattr=a1,+a2,-a3,...
Override or control specific attributes of the target, such as whether SIMD
operations are enabled or not. The default set of attributes is set by the
current CPU. For a list of available attributes, use:
**llvm-as < /dev/null | llc -march=xyz -mattr=help**
FLOATING POINT OPTIONS
----------------------
**-disable-excess-fp-precision**
.. option:: -disable-excess-fp-precision
Disable optimizations that may increase floating point precision.
**-enable-no-infs-fp-math**
.. option:: -enable-no-infs-fp-math
Enable optimizations that assume no Inf values.
**-enable-no-nans-fp-math**
.. option:: -enable-no-nans-fp-math
Enable optimizations that assume no NAN values.
.. option:: -enable-unsafe-fp-math
**-enable-unsafe-fp-math**
Causes **lli** to enable optimizations that may decrease floating point
Causes :program:`lli` to enable optimizations that may decrease floating point
precision.
.. option:: -soft-float
**-soft-float**
Causes **lli** to generate software floating point library calls instead of
Causes :program:`lli` to generate software floating point library calls instead of
equivalent hardware instructions.
CODE GENERATION OPTIONS
-----------------------
**-code-model**\ =\ *model*
.. option:: -code-model=model
Choose the code model from:
.. code-block:: perl
default: Target default code model
@ -175,42 +130,30 @@ CODE GENERATION OPTIONS
medium: Medium code model
large: Large code model
**-disable-post-RA-scheduler**
.. option:: -disable-post-RA-scheduler
Disable scheduling after register allocation.
**-disable-spill-fusing**
.. option:: -disable-spill-fusing
Disable fusing of spill code into instructions.
**-jit-enable-eh**
.. option:: -jit-enable-eh
Exception handling should be enabled in the just-in-time compiler.
**-join-liveintervals**
.. option:: -join-liveintervals
Coalesce copies (default=true).
.. option:: -nozero-initialized-in-bss
Don't place zero-initialized symbols into the BSS section.
**-nozero-initialized-in-bss** Don't place zero-initialized symbols into the BSS section.
**-pre-RA-sched**\ =\ *scheduler*
.. option:: -pre-RA-sched=scheduler
Instruction schedulers available (before register allocation):
.. code-block:: perl
=default: Best scheduler for the target
@ -221,74 +164,51 @@ CODE GENERATION OPTIONS
=list-tdrr: Top-down register reduction list scheduling
=list-td: Top-down list scheduler -print-machineinstrs - Print generated machine code
**-regalloc**\ =\ *allocator*
.. option:: -regalloc=allocator
Register allocator to use (default=linearscan)
.. code-block:: perl
=bigblock: Big-block register allocator
=linearscan: linear scan register allocator =local - local register allocator
=simple: simple register allocator
**-relocation-model**\ =\ *model*
.. option:: -relocation-model=model
Choose relocation model from:
.. code-block:: perl
=default: Target default relocation model
=static: Non-relocatable code =pic - Fully relocatable, position independent code
=dynamic-no-pic: Relocatable external references, non-relocatable code
**-spiller**
.. option:: -spiller
Spiller to use (default=local)
.. code-block:: perl
=simple: simple spiller
=local: local spiller
**-x86-asm-syntax**\ =\ *syntax*
.. option:: -x86-asm-syntax=syntax
Choose style of code to emit from X86 backend:
.. code-block:: perl
=att: Emit AT&T-style assembly
=intel: Emit Intel-style assembly
EXIT STATUS
-----------
If **lli** fails to load the program, it will exit with an exit code of 1.
If :program:`lli` fails to load the program, it will exit with an exit code of 1.
Otherwise, it will return the exit code of the program it executes.
SEE ALSO
--------
llc|llc
:program:`llc`

View File

@ -26,5 +26,5 @@ OPTIONS
EXIT STATUS
-----------
:program:`llvm-dwarfdump` returns 0. Other exit codes imply internal
program error.
:program:`llvm-dwarfdump` returns 0 if the input files were parsed and dumped
successfully. Otherwise, it returns 1.

View File

@ -0,0 +1,31 @@
llvm-lib - LLVM lib.exe compatible library tool
===============================================
SYNOPSIS
--------
**llvm-lib** [/libpath:<path>] [/out:<output>] [/llvmlibthin]
[/ignore] [/machine] [/nologo] [files...]
DESCRIPTION
-----------
The **llvm-lib** command is intended to be a ``lib.exe`` compatible
tool. See https://msdn.microsoft.com/en-us/library/7ykb2k5f for the
general description.
**llvm-lib** has the following extensions:
* Bitcode files in symbol tables.
**llvm-lib** includes symbols from both bitcode files and regular
object files in the symbol table.
* Creating thin archives.
The /llvmlibthin option causes **llvm-lib** to create thin archive
that contain only the symbol table and the header for the various
members. These files are much smaller, but are not compatible with
link.exe (lld can handle them).

View File

@ -1737,6 +1737,7 @@ exported by the ``lib/VMCore/PassManager.cpp`` file.
.. _dynamically loaded options:
Dynamically adding command line options
---------------------------------------
.. todo::

View File

@ -405,7 +405,7 @@ LEB128 is an unsigned interger value that is encoded using DWARF's LEB128
encoding, optimizing for the case where values are small
(1 byte for values less than 128).
.. _strings:
.. _Strings:
Strings
^^^^^^^

View File

@ -624,5 +624,5 @@ patent-related trouble with their changes (including from third parties). If
you or your employer own the rights to a patent and would like to contribute
code to LLVM that relies on it, we require that the copyright owner sign an
agreement that allows any other user of LLVM to freely use your patent. Please
contact the `oversight group <mailto:llvm-oversight@cs.uiuc.edu>`_ for more
contact the `LLVM Foundation Board of Directors <mailto:board@llvm.org>`_ for more
details.

View File

@ -339,11 +339,11 @@ original context before code generation.
Catch handlers are called with a pointer to the handler itself as the first
argument and a pointer to the parent function's stack frame as the second
argument. The catch handler uses the `llvm.recoverframe
<LangRef.html#llvm-frameallocate-and-llvm-framerecover-intrinsics>`_ to get a
argument. The catch handler uses the `llvm.localrecover
<LangRef.html#llvm-localescape-and-llvm-localrecover-intrinsics>`_ to get a
pointer to a frame allocation block that is created in the parent frame using
the `llvm.allocateframe
<LangRef.html#llvm-frameallocate-and-llvm-framerecover-intrinsics>`_ intrinsic.
the `llvm.localescape
<LangRef.html#llvm-localescape-and-llvm-localrecover-intrinsics>`_ intrinsic.
The ``WinEHPrepare`` pass will have created a structure definition for the
contents of this block. The first two members of the structure will always be
(1) a 32-bit integer that the runtime uses to track the exception state of the
@ -520,12 +520,12 @@ action.
A code of ``i32 1`` indicates a catch action, which expects three additional
arguments. Different EH schemes give different meanings to the three arguments,
but the first argument indicates whether the catch should fire, the second is
the frameescape index of the exception object, and the third is the code to run
the localescape index of the exception object, and the third is the code to run
to catch the exception.
For Windows C++ exception handling, the first argument for a catch handler is a
pointer to the RTTI type descriptor for the object to catch. The second
argument is an index into the argument list of the ``llvm.frameescape`` call in
argument is an index into the argument list of the ``llvm.localescape`` call in
the main function. The exception object will be copied into the provided stack
object. If the exception object is not required, this argument should be -1.
The third argument is a pointer to a function implementing the catch. This

View File

@ -49,6 +49,79 @@ The format of this section is
FunctionFaultInfo[NumFaultingPCs] {
uint32 : FaultKind = FaultMaps::FaultingLoad (only legal value currently)
uint32 : FaultingPCOffset
uint32 : handlerPCOffset
uint32 : HandlerPCOffset
}
}
The ``ImplicitNullChecks`` pass
===============================
The ``ImplicitNullChecks`` pass transforms explicit control flow for
checking if a pointer is ``null``, like:
.. code-block:: llvm
%ptr = call i32* @get_ptr()
%ptr_is_null = icmp i32* %ptr, null
br i1 %ptr_is_null, label %is_null, label %not_null, !make.implicit !0
not_null:
%t = load i32, i32* %ptr
br label %do_something_with_t
is_null:
call void @HFC()
unreachable
!0 = !{}
to control flow implicit in the instruction loading or storing through
the pointer being null checked:
.. code-block:: llvm
%ptr = call i32* @get_ptr()
%t = load i32, i32* %ptr ;; handler-pc = label %is_null
br label %do_something_with_t
is_null:
call void @HFC()
unreachable
This transform happens at the ``MachineInstr`` level, not the LLVM IR
level (so the above example is only representative, not literal). The
``ImplicitNullChecks`` pass runs during codegen, if
``-enable-implicit-null-checks`` is passed to ``llc``.
The ``ImplicitNullChecks`` pass adds entries to the
``__llvm_faultmaps`` section described above as needed.
``make.implicit`` metadata
--------------------------
Making null checks implicit is an aggressive optimization, and it can
be a net performance pessimization if too many memory operations end
up faulting because of it. A language runtime typically needs to
ensure that only a negligible number of implicit null checks actually
fault once the application has reached a steady state. A standard way
of doing this is by healing failed implicit null checks into explicit
null checks via code patching or recompilation. It follows that there
are two requirements an explicit null check needs to satisfy for it to
be profitable to convert it to an implicit null check:
1. The case where the pointer is actually null (i.e. the "failing"
case) is extremely rare.
2. The failing path heals the implicit null check into an explicit
null check so that the application does not repeatedly page
fault.
The frontend is expected to mark branches that satisfy (1) and (2)
using a ``!make.implicit`` metadata node (the actual content of the
metadata node is ignored). Only branches that are marked with
``!make.implicit`` metadata are considered as candidates for
conversion into implicit null checks.
(Note that while we could deal with (1) using profiling data, dealing
with (2) requires some information not present in branch profiles.)

View File

@ -326,7 +326,11 @@ Easy steps for installing GCC 4.8.2:
.. code-block:: console
% wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2
% wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2
% wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2.sig
% wget https://ftp.gnu.org/gnu/gnu-keyring.gpg
% signature_invalid=`gpg --verify --no-default-keyring --keyring ./gnu-keyring.gpg gcc-4.8.2.tar.bz2.sig`
% if [ $signature_invalid ]; then echo "Invalid signature" ; exit 1 ; fi
% tar -xvjf gcc-4.8.2.tar.bz2
% cd gcc-4.8.2
% ./contrib/download_prerequisites

View File

@ -136,51 +136,24 @@ Regenerate the configure scripts for both ``llvm`` and the ``test-suite``.
In addition, the version numbers of all the Bugzilla components must be updated
for the next release.
Build the LLVM Release Candidates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Tagging the LLVM Release Candidates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Create release candidates for ``llvm``, ``clang``, ``dragonegg``, and the LLVM
``test-suite`` by tagging the branch with the respective release candidate
number. For instance, to create **Release Candidate 1** you would issue the
following commands:
Tag release candidates using the tag.sh script in utils/release.
::
$ svn mkdir https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ
$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \
https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/rc1
$ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ
$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/rc1
$ svn mkdir https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ
$ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \
https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/rc1
$ svn mkdir https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ
$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \
https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/rc1
Similarly, **Release Candidate 2** would be named ``RC2`` and so on. This keeps
a permanent copy of the release candidate around for people to export and build
as they wish. The final released sources will be tagged in the ``RELEASE_XYZ``
directory as ``Final`` (c.f. :ref:`tag`).
$ ./tag.sh -release X.Y.Z -rc $RC
The Release Manager may supply pre-packaged source tarballs for users. This can
be done with the following commands:
be done with the export.sh script in utils/release.
::
$ svn export https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/rc1 llvm-X.Yrc1
$ svn export https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/rc1 clang-X.Yrc1
$ svn export https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/rc1 dragonegg-X.Yrc1
$ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/rc1 llvm-test-X.Yrc1
$ ./export.sh -release X.Y.Z -rc $RC
$ tar -cvf - llvm-X.Yrc1 | gzip > llvm-X.Yrc1.src.tar.gz
$ tar -cvf - clang-X.Yrc1 | gzip > clang-X.Yrc1.src.tar.gz
$ tar -cvf - dragonegg-X.Yrc1 | gzip > dragonegg-X.Yrc1.src.tar.gz
$ tar -cvf - llvm-test-X.Yrc1 | gzip > llvm-test-X.Yrc1.src.tar.gz
This will generate source tarballs for each LLVM project being validated, which
can be uploaded to the website for further testing.
Building the Release
--------------------
@ -384,21 +357,11 @@ mainline into the release branch.
Tag the LLVM Final Release
^^^^^^^^^^^^^^^^^^^^^^^^^^
Tag the final release sources using the following procedure:
Tag the final release sources using the tag.sh script in utils/release.
::
$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \
https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/Final
$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/Final
$ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \
https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/Final
$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \
https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/Final
$ ./tag.sh -release X.Y.Z -final
Update the LLVM Demo Page
-------------------------

File diff suppressed because it is too large Load Diff

View File

@ -112,7 +112,7 @@ Here we show how to use lib/Fuzzer on something real, yet simple: pcre2_::
(cd pcre; ./autogen.sh; CC="clang -fsanitize=address $COV_FLAGS" ./configure --prefix=`pwd`/../inst && make -j && make install)
# Build lib/Fuzzer files.
clang -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
# Build the the actual function that does something interesting with PCRE2.
# Build the actual function that does something interesting with PCRE2.
cat << EOF > pcre_fuzzer.cc
#include <string.h>
#include "pcre2posix.h"

View File

@ -60,26 +60,28 @@ to upload your patch):
To upload a new patch:
* Click *Differential*.
* Click *Create Diff*.
* Paste the text diff or upload the patch file.
Note that TODO
* Click *+ Create Diff*.
* Paste the text diff or browse to the patch file. Click *Create Diff*.
* Leave the Repository field blank.
* Leave the drop down on *Create a new Revision...* and click *Continue*.
* Enter a descriptive title and summary. The title and summary are usually
in the form of a :ref:`commit message <commit messages>`.
* Add reviewers and mailing
lists that you want to be included in the review. If your patch is
for LLVM, add llvm-commits as a subscriber; if your patch is for Clang,
for LLVM, add llvm-commits as a Subscriber; if your patch is for Clang,
add cfe-commits.
* Leave the Repository and Project fields blank.
* Click *Save*.
To submit an updated patch:
* Click *Differential*.
* Click *Create Diff*.
* Paste the updated diff.
* Click *+ Create Diff*.
* Paste the updated diff or browse to the updated patch file. Click *Create Diff*.
* Select the review you want to from the *Attach To* dropdown and click
*Continue*.
* Click *Save*.
* Leave the Repository and Project fields blank.
* Add comments about the changes in the new diff. Click *Save*.
Reviewing code with Phabricator
-------------------------------
@ -160,6 +162,6 @@ trivially a good fit for an official LLVM project.
.. _LLVM's Phabricator: http://reviews.llvm.org
.. _`http://reviews.llvm.org`: http://reviews.llvm.org
.. _Code Repository Browser: http://reviews.llvm.org/diffusion/
.. _Arcanist Quick Start: http://www.phabricator.com/docs/phabricator/article/Arcanist_Quick_Start.html
.. _Arcanist User Guide: http://www.phabricator.com/docs/phabricator/article/Arcanist_User_Guide.html
.. _Arcanist Quick Start: https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/
.. _Arcanist User Guide: https://secure.phabricator.com/book/phabricator/article/arcanist/
.. _llvm-reviews GitHub project: https://github.com/r4nt/llvm-reviews/

View File

@ -1868,7 +1868,7 @@ Iterating over predecessors & successors of blocks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Iterating over the predecessors and successors of a block is quite easy with the
routines defined in ``"llvm/Support/CFG.h"``. Just use code like this to
routines defined in ``"llvm/IR/CFG.h"``. Just use code like this to
iterate over all predecessors of BB:
.. code-block:: c++

View File

@ -1,12 +1,12 @@
======================
LLVM 3.7 Release Notes
LLVM 3.8 Release Notes
======================
.. contents::
:local:
.. warning::
These are in-progress notes for the upcoming LLVM 3.7 release. You may
These are in-progress notes for the upcoming LLVM 3.8 release. You may
prefer the `LLVM 3.6 Release Notes <http://llvm.org/releases/3.6.0/docs
/ReleaseNotes.html>`_.
@ -15,7 +15,7 @@ Introduction
============
This document contains the release notes for the LLVM Compiler Infrastructure,
release 3.7. Here we describe the status of LLVM, including major improvements
release 3.8. Here we describe the status of LLVM, including major improvements
from the previous release, improvements in various subprojects of LLVM, and
some of the current users of the code. All LLVM releases may be downloaded
from the `LLVM releases web site <http://llvm.org/releases/>`_.
@ -41,18 +41,6 @@ Non-comprehensive list of changes in this release
functionality, or simply have a lot to talk about), see the `NOTE` below
for adding a new subsection.
* The minimum required Visual Studio version for building LLVM is now 2013
Update 4.
* A new documentation page, :doc:`Frontend/PerformanceTips`, contains a
collection of tips for frontend authors on how to generate IR which LLVM is
able to effectively optimize.
* The DataLayout is no longer optional. All the IR level optimizations expects
it to be present and the API has been changed to use a reference instead of
a pointer to make it explicit. The Module owns the datalayout and it has to
match the one attached to the TargetMachine for generating code.
* ... next change ...
.. NOTE
@ -89,12 +77,12 @@ Changes to the OCaml bindings
During this release ...
External Open Source Projects Using LLVM 3.7
External Open Source Projects Using LLVM 3.8
============================================
An exciting aspect of LLVM is that it is used as an enabling technology for
a lot of other language and tools projects. This section lists some of the
projects that have already been updated to work with LLVM 3.7.
projects that have already been updated to work with LLVM 3.8.
* A project

View File

@ -221,12 +221,10 @@ lowered according to the calling convention specified at the
intrinsic's callsite. Variants of the intrinsic with non-void return
type also return a value according to calling convention.
On PowerPC, note that ``<target>`` must be the actual intended target of
the indirect call. Specifically, even when compiling for the ELF V1 ABI,
``<target>`` is not the function-descriptor address normally used as the C/C++
function-pointer representation. As a result, the call target must be local
because no adjustment or restoration of the TOC pointer (in register r2) will
be performed.
On PowerPC, note that ``<target>`` must be the ABI function pointer for the
intended target of the indirect call. Specifically, when compiling for the
ELF V1 ABI, ``<target>`` is the function-descriptor address normally used as
the C/C++ function-pointer representation.
Requesting zero patch point arguments is valid. In this case, all
variable operands are handled just like
@ -501,3 +499,13 @@ the same requirement imposed by the llvm.gcroot intrinsic.) LLVM
transformations must not substitute the alloca with any intervening
value. This can be verified by the runtime simply by checking that the
stack map's location is a Direct location type.
Supported Architectures
=======================
Support for StackMap generation and the related intrinsics requires
some code for each backend. Today, only a subset of LLVM's backends
are supported. The currently supported architectures are X86_64,
PowerPC, and Aarch64.

View File

@ -331,14 +331,16 @@ the user will patch over the 'num patch bytes' bytes of nops with a
calling sequence specific to their runtime before executing the
generated machine code. There are no guarantees with respect to the
alignment of the nop sequence. Unlike :doc:`StackMaps` statepoints do
not have a concept of shadow bytes.
not have a concept of shadow bytes. Note that semantically the
statepoint still represents a call or invoke to 'target', and the nop
sequence after patching is expected to represent an operation
equivalent to a call or invoke to 'target'.
The 'target' operand is the function actually being called. The
target can be specified as either a symbolic LLVM function, or as an
arbitrary Value of appropriate function type. Note that the function
type must match the signature of the callee and the types of the 'call
parameters' arguments. If 'num patch bytes' is non-zero then 'target'
has to be the constant pointer null of the appropriate function type.
parameters' arguments.
The '#call args' operand is the number of arguments to the actual
call. It must exactly match the number of arguments passed in the
@ -699,6 +701,12 @@ deoptimization or introspection) at safepoints. In that case, ask on the
llvmdev mailing list for suggestions.
Supported Architectures
=======================
Support for statepoint generation requires some code for each backend.
Today, only X86_64 is supported.
Bugs and Enhancements
=====================

97
docs/_ocamldoc/style.css Normal file
View File

@ -0,0 +1,97 @@
/* A style for ocamldoc. Daniel C. Buenzli */
/* Reset a few things. */
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,
a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,
small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,
form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td
{ margin: 0; padding: 0; border: 0 none; outline: 0; font-size: 100%;
font-weight: inherit; font-style:inherit; font-family:inherit;
line-height: inherit; vertical-align: baseline; text-align:inherit;
color:inherit; background: transparent; }
table { border-collapse: collapse; border-spacing: 0; }
/* Basic page layout */
body { font: normal 10pt/1.375em helvetica, arial, sans-serif; text-align:left;
margin: 1.375em 10%; min-width: 40ex; max-width: 72ex;
color: black; background: transparent /* url(line-height-22.gif) */; }
b { font-weight: bold }
em { font-style: italic }
tt, code, pre { font-family: WorkAroundWebKitAndMozilla, monospace;
font-size: 1em; }
pre code { font-size : inherit; }
.codepre { margin-bottom:1.375em /* after code example we introduce space. */ }
.superscript,.subscript
{ font-size : 0.813em; line-height:0; margin-left:0.4ex;}
.superscript { vertical-align: super; }
.subscript { vertical-align: sub; }
/* ocamldoc markup workaround hacks */
hr, hr + br, div + br, center + br, span + br, ul + br, ol + br, pre + br
{ display: none } /* annoying */
div.info + br { display:block}
.codepre br + br { display: none }
h1 + pre { margin-bottom:1.375em} /* Toplevel module description */
/* Sections and document divisions */
/* .navbar { margin-bottom: -1.375em } */
h1 { font-weight: bold; font-size: 1.5em; /* margin-top:1.833em; */
margin-top:0.917em; padding-top:0.875em;
border-top-style:solid; border-width:1px; border-color:#AAA; }
h2 { font-weight: bold; font-size: 1.313em; margin-top: 1.048em }
h3 { font-weight: bold; font-size: 1.125em; margin-top: 1.222em }
h3 { font-weight: bold; font-size: 1em; margin-top: 1.375em}
h4 { font-style: italic; }
/* Used by OCaml's own library documentation. */
h6 { font-weight: bold; font-size: 1.125em; margin-top: 1.222em }
.h7 { font-weight: bold; font-size: 1em; margin-top: 1.375em }
p { margin-top: 1.375em }
pre { margin-top: 1.375em }
.info { margin: 0.458em 0em -0.458em 2em;}/* Description of types values etc. */
td .info { margin:0; padding:0; margin-left: 2em;} /* Description in indexes */
ul, ol { margin-top:0.688em; padding-bottom:0.687em;
list-style-position:outside}
ul + p, ol + p { margin-top: 0em }
ul { list-style-type: square }
/* h2 + ul, h3 + ul, p + ul { } */
ul > li { margin-left: 1.375em; }
ol > li { margin-left: 1.7em; }
/* Links */
a, a:link, a:visited, a:active, a:hover { color : #00B; text-decoration: none }
a:hover { text-decoration : underline }
*:target {background-color: #FFFF99;} /* anchor highlight */
/* Code */
.keyword { font-weight: bold; }
.comment { color : red }
.constructor { color : green }
.string { color : brown }
.warning { color : red ; font-weight : bold }
/* Functors */
.paramstable { border-style : hidden ; padding-bottom:1.375em}
.paramstable code { margin-left: 1ex; margin-right: 1ex }
.sig_block {margin-left: 1em}
/* Images */
img { margin-top: 1.375em }

View File

@ -47,9 +47,9 @@ copyright = u'2003-2014, LLVM Project'
# built documents.
#
# The short X.Y version.
version = '3.7'
version = '3.8'
# The full version, including alpha/beta/rc tags.
release = '3.7'
release = '3.8'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.

View File

@ -395,9 +395,8 @@ argument allocas in ``PrototypeAST::CreateArgumentAllocas``.
DIScope *Scope = KSDbgInfo.LexicalBlocks.back();
DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(),
KSDbgInfo.TheCU.getDirectory());
DILocalVariable D = DBuilder->createLocalVariable(
dwarf::DW_TAG_arg_variable, Scope, Args[Idx], Unit, Line,
KSDbgInfo.getDoubleTy(), Idx);
DILocalVariable D = DBuilder->createParameterVariable(
Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true);
Instruction *Call = DBuilder->insertDeclare(
Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock());

View File

@ -65,6 +65,7 @@ Here's a simplified Kwalify_ schema with an extension to allow alternate types.
, IMAGE_FILE_MACHINE_AMD64
, IMAGE_FILE_MACHINE_ARM
, IMAGE_FILE_MACHINE_ARMNT
, IMAGE_FILE_MACHINE_ARM64
, IMAGE_FILE_MACHINE_EBC
, IMAGE_FILE_MACHINE_I386
, IMAGE_FILE_MACHINE_IA64

View File

@ -560,7 +560,7 @@ void *MCJITHelper::getPointerToFunction(Function *F) {
// Set up the optimizer pipeline. Start with registering info about how the
// target lays out data structures.
OpenModule->setDataLayout(*NewEngine->getDataLayout());
OpenModule->setDataLayout(NewEngine->getDataLayout());
// Provide basic AliasAnalysis support for GVN.
FPM->add(createBasicAliasAnalysisPass());
// Promote allocas to registers.

View File

@ -913,7 +913,7 @@ int main() {
// Set up the optimizer pipeline. Start with registering info about how the
// target lays out data structures.
TheModule->setDataLayout(*TheExecutionEngine->getDataLayout());
TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
// Provide basic AliasAnalysis support for GVN.
OurFPM.add(createBasicAliasAnalysisPass());
// Do simple "peephole" optimizations and bit-twiddling optzns.

View File

@ -1034,7 +1034,7 @@ int main() {
// Set up the optimizer pipeline. Start with registering info about how the
// target lays out data structures.
TheModule->setDataLayout(*TheExecutionEngine->getDataLayout());
TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
// Provide basic AliasAnalysis support for GVN.
OurFPM.add(createBasicAliasAnalysisPass());
// Do simple "peephole" optimizations and bit-twiddling optzns.

View File

@ -1211,7 +1211,7 @@ int main() {
// Set up the optimizer pipeline. Start with registering info about how the
// target lays out data structures.
TheModule->setDataLayout(*TheExecutionEngine->getDataLayout());
TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
// Provide basic AliasAnalysis support for GVN.
OurFPM.add(createBasicAliasAnalysisPass());
// Promote allocas to registers.

View File

@ -1253,9 +1253,8 @@ void PrototypeAST::CreateArgumentAllocas(Function *F) {
DIScope *Scope = KSDbgInfo.LexicalBlocks.back();
DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(),
KSDbgInfo.TheCU->getDirectory());
DILocalVariable *D = DBuilder->createLocalVariable(
dwarf::DW_TAG_arg_variable, Scope, Args[Idx], Unit, Line,
KSDbgInfo.getDoubleTy(), Idx);
DILocalVariable *D = DBuilder->createParameterVariable(
Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true);
DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(),
DebugLoc::get(Line, 0, Scope),
@ -1462,7 +1461,7 @@ int main() {
// Set up the optimizer pipeline. Start with registering info about how the
// target lays out data structures.
TheModule->setDataLayout(*TheExecutionEngine->getDataLayout());
TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
#if 0
// Provide basic AliasAnalysis support for GVN.
OurFPM.add(createBasicAliasAnalysisPass());

View File

@ -717,7 +717,7 @@ public:
M(new Module(GenerateUniqueName("jit_module_"),
Session.getLLVMContext())),
Builder(Session.getLLVMContext()) {
M->setDataLayout(*Session.getTarget().getDataLayout());
M->setDataLayout(Session.getTarget().createDataLayout());
}
SessionContext& getSession() { return Session; }
@ -1168,7 +1168,6 @@ public:
KaleidoscopeJIT(SessionContext &Session)
: Session(Session),
Mang(Session.getTarget().getDataLayout()),
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())),
LazyEmitLayer(CompileLayer),
CompileCallbacks(LazyEmitLayer, CCMgrMemMgr, Session.getLLVMContext(),
@ -1179,7 +1178,8 @@ public:
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, Name);
Mangler::getNameWithPrefix(MangledNameStream, Name,
Session.getTarget().createDataLayout());
}
return MangledName;
}
@ -1306,7 +1306,6 @@ private:
}
SessionContext &Session;
Mangler Mang;
SectionMemoryManager CCMgrMemMgr;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;

View File

@ -716,7 +716,7 @@ public:
M(new Module(GenerateUniqueName("jit_module_"),
Session.getLLVMContext())),
Builder(Session.getLLVMContext()) {
M->setDataLayout(*Session.getTarget().getDataLayout());
M->setDataLayout(Session.getTarget().createDataLayout());
}
SessionContext& getSession() { return Session; }
@ -1160,14 +1160,14 @@ public:
typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;
KaleidoscopeJIT(SessionContext &Session)
: Mang(Session.getTarget().getDataLayout()),
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {}
: DL(Session.getTarget().createDataLayout()),
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {}
std::string mangle(const std::string &Name) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, Name);
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
@ -1201,8 +1201,7 @@ public:
}
private:
Mangler Mang;
const DataLayout DL;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
};

View File

@ -716,7 +716,7 @@ public:
M(new Module(GenerateUniqueName("jit_module_"),
Session.getLLVMContext())),
Builder(Session.getLLVMContext()) {
M->setDataLayout(*Session.getTarget().getDataLayout());
M->setDataLayout(Session.getTarget().createDataLayout());
}
SessionContext& getSession() { return Session; }
@ -1162,15 +1162,15 @@ public:
typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT;
KaleidoscopeJIT(SessionContext &Session)
: Mang(Session.getTarget().getDataLayout()),
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())),
LazyEmitLayer(CompileLayer) {}
: DL(Session.getTarget().createDataLayout()),
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())),
LazyEmitLayer(CompileLayer) {}
std::string mangle(const std::string &Name) {
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, Name);
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
}
return MangledName;
}
@ -1204,8 +1204,7 @@ public:
}
private:
Mangler Mang;
const DataLayout DL;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
LazyEmitLayerT LazyEmitLayer;

View File

@ -716,7 +716,7 @@ public:
M(new Module(GenerateUniqueName("jit_module_"),
Session.getLLVMContext())),
Builder(Session.getLLVMContext()) {
M->setDataLayout(*Session.getTarget().getDataLayout());
M->setDataLayout(Session.getTarget().createDataLayout());
}
SessionContext& getSession() { return Session; }
@ -1162,7 +1162,6 @@ public:
KaleidoscopeJIT(SessionContext &Session)
: Session(Session),
Mang(Session.getTarget().getDataLayout()),
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())),
LazyEmitLayer(CompileLayer) {}
@ -1170,7 +1169,8 @@ public:
std::string MangledName;
{
raw_string_ostream MangledNameStream(MangledName);
Mang.getNameWithPrefix(MangledNameStream, Name);
Mangler::getNameWithPrefix(MangledNameStream, Name,
Session.getTarget().createDataLayout());
}
return MangledName;
}
@ -1236,7 +1236,6 @@ private:
}
SessionContext &Session;
Mangler Mang;
ObjLayerT ObjectLayer;
CompileLayerT CompileLayer;
LazyEmitLayerT LazyEmitLayer;

View File

@ -161,15 +161,15 @@ typedef enum {
/* FIXME: These attributes are currently not included in the C API as
a temporary measure until the API/ABI impact to the C API is understood
and the path forward agreed upon.
LLVMAddressSafety = 1ULL << 32,
LLVMStackProtectStrongAttribute = 1ULL<<33,
LLVMCold = 1ULL << 34,
LLVMOptimizeNone = 1ULL << 35,
LLVMInAllocaAttribute = 1ULL << 36,
LLVMNonNullAttribute = 1ULL << 37,
LLVMJumpTableAttribute = 1ULL << 38,
LLVMDereferenceableAttribute = 1ULL << 39,
LLVMDereferenceableOrNullAttribute = 1ULL << 40,
LLVMSanitizeAddressAttribute = 1ULL << 32,
LLVMStackProtectStrongAttribute = 1ULL<<35,
LLVMColdAttribute = 1ULL << 40,
LLVMOptimizeNoneAttribute = 1ULL << 42,
LLVMInAllocaAttribute = 1ULL << 43,
LLVMNonNullAttribute = 1ULL << 44,
LLVMJumpTableAttribute = 1ULL << 45,
LLVMConvergentAttribute = 1ULL << 46,
LLVMSafeStackAttribute = 1ULL << 47,
*/
} LLVMAttribute;
@ -248,7 +248,13 @@ typedef enum {
/* Exception Handling Operators */
LLVMResume = 58,
LLVMLandingPad = 59
LLVMLandingPad = 59,
LLVMCleanupRet = 61,
LLVMCatchRet = 62,
LLVMCatchPad = 63,
LLVMTerminatePad = 64,
LLVMCleanupPad = 65,
LLVMCatchEndPad = 66
} LLVMOpcode;
@ -1203,6 +1209,7 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(InsertElementInst) \
macro(InsertValueInst) \
macro(LandingPadInst) \
macro(CleanupPadInst) \
macro(PHINode) \
macro(SelectInst) \
macro(ShuffleVectorInst) \
@ -1215,6 +1222,11 @@ LLVMTypeRef LLVMX86MMXType(void);
macro(SwitchInst) \
macro(UnreachableInst) \
macro(ResumeInst) \
macro(CleanupReturnInst) \
macro(CatchReturnInst) \
macro(CatchPadInst) \
macro(TerminatePadInst) \
macro(CatchEndPadInst) \
macro(UnaryInstruction) \
macro(AllocaInst) \
macro(CastInst) \
@ -1887,6 +1899,20 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee,
*/
void LLVMDeleteFunction(LLVMValueRef Fn);
/**
* Obtain the personality function attached to the function.
*
* @see llvm::Function::getPersonalityFn()
*/
LLVMValueRef LLVMGetPersonalityFn(LLVMValueRef Fn);
/**
* Set the personality function attached to the function.
*
* @see llvm::Function::setPersonalityFn()
*/
void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn);
/**
* Obtain the ID number from a function instance.
*
@ -1936,7 +1962,7 @@ void LLVMSetGC(LLVMValueRef Fn, const char *Name);
void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA);
/**
* Add a target-dependent attribute to a fuction
* Add a target-dependent attribute to a function
* @see llvm::AttrBuilder::addAttribute()
*/
void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A,

View File

@ -81,7 +81,6 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI);
uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI);
// RelocationRef accessors
uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI);
uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI);
LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI);
uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI);

View File

@ -40,7 +40,7 @@ typedef bool lto_bool_t;
* @{
*/
#define LTO_API_VERSION 15
#define LTO_API_VERSION 17
/**
* \since prior to LTO_API_VERSION=3
@ -63,7 +63,8 @@ typedef enum {
LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000,
LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800,
LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800,
LTO_SYMBOL_COMDAT = 0x00004000
LTO_SYMBOL_COMDAT = 0x00004000,
LTO_SYMBOL_ALIAS = 0x00008000
} lto_symbol_attributes;
/**
@ -280,39 +281,15 @@ lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index);
/**
* Returns the number of dependent libraries in the object module.
* Returns the module's linker options.
*
* \since LTO_API_VERSION=8
*/
extern unsigned int
lto_module_get_num_deplibs(lto_module_t mod);
/**
* Returns the ith dependent library in the module.
* The linker options may consist of multiple flags. It is the linker's
* responsibility to split the flags using a platform-specific mechanism.
*
* \since LTO_API_VERSION=8
* \since LTO_API_VERSION=16
*/
extern const char*
lto_module_get_deplib(lto_module_t mod, unsigned int index);
/**
* Returns the number of linker options in the object module.
*
* \since LTO_API_VERSION=8
*/
extern unsigned int
lto_module_get_num_linkeropts(lto_module_t mod);
/**
* Returns the ith linker option in the module.
*
* \since LTO_API_VERSION=8
*/
extern const char*
lto_module_get_linkeropt(lto_module_t mod, unsigned int index);
lto_module_get_linkeropts(lto_module_t mod);
/**

View File

@ -276,6 +276,10 @@ public:
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
/// Returns the size of the floating point number (in bits) in the given
/// semantics.
static unsigned getSizeInBits(const fltSemantics &Sem);
/// @}
/// Used to insert APFloat objects, or objects that contain APFloat objects,

View File

@ -1038,7 +1038,9 @@ public:
/// the validity of the less-than relationship.
///
/// \returns true if *this < RHS when considered unsigned.
bool ult(uint64_t RHS) const { return ult(APInt(getBitWidth(), RHS)); }
bool ult(uint64_t RHS) const {
return getActiveBits() > 64 ? false : getZExtValue() < RHS;
}
/// \brief Signed less than comparison
///
@ -1054,7 +1056,9 @@ public:
/// the validity of the less-than relationship.
///
/// \returns true if *this < RHS when considered signed.
bool slt(uint64_t RHS) const { return slt(APInt(getBitWidth(), RHS)); }
bool slt(int64_t RHS) const {
return getMinSignedBits() > 64 ? isNegative() : getSExtValue() < RHS;
}
/// \brief Unsigned less or equal comparison
///
@ -1070,7 +1074,7 @@ public:
/// the validity of the less-or-equal relationship.
///
/// \returns true if *this <= RHS when considered unsigned.
bool ule(uint64_t RHS) const { return ule(APInt(getBitWidth(), RHS)); }
bool ule(uint64_t RHS) const { return !ugt(RHS); }
/// \brief Signed less or equal comparison
///
@ -1086,7 +1090,7 @@ public:
/// validity of the less-or-equal relationship.
///
/// \returns true if *this <= RHS when considered signed.
bool sle(uint64_t RHS) const { return sle(APInt(getBitWidth(), RHS)); }
bool sle(uint64_t RHS) const { return !sgt(RHS); }
/// \brief Unsigned greather than comparison
///
@ -1102,7 +1106,9 @@ public:
/// the validity of the greater-than relationship.
///
/// \returns true if *this > RHS when considered unsigned.
bool ugt(uint64_t RHS) const { return ugt(APInt(getBitWidth(), RHS)); }
bool ugt(uint64_t RHS) const {
return getActiveBits() > 64 ? true : getZExtValue() > RHS;
}
/// \brief Signed greather than comparison
///
@ -1118,7 +1124,9 @@ public:
/// the validity of the greater-than relationship.
///
/// \returns true if *this > RHS when considered signed.
bool sgt(uint64_t RHS) const { return sgt(APInt(getBitWidth(), RHS)); }
bool sgt(int64_t RHS) const {
return getMinSignedBits() > 64 ? !isNegative() : getSExtValue() > RHS;
}
/// \brief Unsigned greater or equal comparison
///
@ -1134,7 +1142,7 @@ public:
/// the validity of the greater-or-equal relationship.
///
/// \returns true if *this >= RHS when considered unsigned.
bool uge(uint64_t RHS) const { return uge(APInt(getBitWidth(), RHS)); }
bool uge(uint64_t RHS) const { return !ult(RHS); }
/// \brief Signed greather or equal comparison
///
@ -1150,7 +1158,7 @@ public:
/// the validity of the greater-or-equal relationship.
///
/// \returns true if *this >= RHS when considered signed.
bool sge(uint64_t RHS) const { return sge(APInt(getBitWidth(), RHS)); }
bool sge(int64_t RHS) const { return !slt(RHS); }
/// This operation tests if there are any pairs of corresponding bits
/// between this APInt and RHS that are both set.

View File

@ -33,6 +33,15 @@ public:
explicit APSInt(APInt I, bool isUnsigned = true)
: APInt(std::move(I)), IsUnsigned(isUnsigned) {}
/// Construct an APSInt from a string representation.
///
/// This constructor interprets the string \p Str using the radix of 10.
/// The interpretation stops at the end of the string. The bit width of the
/// constructed APSInt is determined automatically.
///
/// \param Str the string to be interpreted.
explicit APSInt(StringRef Str);
APSInt &operator=(APInt RHS) {
// Retain our current sign.
APInt::operator=(std::move(RHS));

View File

@ -85,7 +85,7 @@ namespace llvm {
/// Construct an ArrayRef from a std::initializer_list.
/*implicit*/ ArrayRef(const std::initializer_list<T> &Vec)
: Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()),
: Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()),
Length(Vec.size()) {}
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
@ -286,6 +286,11 @@ namespace llvm {
return MutableArrayRef<T>(data()+N, M);
}
MutableArrayRef<T> drop_back(unsigned N) const {
assert(this->size() >= N && "Dropping more elements than exist");
return slice(0, this->size() - N);
}
/// @}
/// @name Operator Overloads
/// @{

View File

@ -14,6 +14,8 @@
#ifndef LLVM_ADT_DENSEMAPINFO_H
#define LLVM_ADT_DENSEMAPINFO_H
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/PointerLikeTypeTraits.h"
#include "llvm/Support/type_traits.h"
@ -163,6 +165,31 @@ struct DenseMapInfo<std::pair<T, U> > {
}
};
// Provide DenseMapInfo for StringRefs.
template <> struct DenseMapInfo<StringRef> {
static inline StringRef getEmptyKey() {
return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
0);
}
static inline StringRef getTombstoneKey() {
return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
0);
}
static unsigned getHashValue(StringRef Val) {
assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
assert(Val.data() != getTombstoneKey().data() &&
"Cannot hash the tombstone key!");
return (unsigned)(hash_value(Val));
}
static bool isEqual(StringRef LHS, StringRef RHS) {
if (RHS.data() == getEmptyKey().data())
return LHS.data() == getEmptyKey().data();
if (RHS.data() == getTombstoneKey().data())
return LHS.data() == getTombstoneKey().data();
return LHS == RHS;
}
};
} // end namespace llvm
#endif

View File

@ -196,6 +196,41 @@ inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) {
return mapped_iterator<ItTy, FuncTy>(I, F);
}
/// \brief Metafunction to determine if type T has a member called rbegin().
template <typename T> struct has_rbegin {
template <typename U> static char(&f(const U &, decltype(&U::rbegin)))[1];
static char(&f(...))[2];
const static bool value = sizeof(f(std::declval<T>(), nullptr)) == 1;
};
// Returns an iterator_range over the given container which iterates in reverse.
// Note that the container must have rbegin()/rend() methods for this to work.
template <typename ContainerTy>
auto reverse(ContainerTy &&C,
typename std::enable_if<has_rbegin<ContainerTy>::value>::type * =
nullptr) -> decltype(make_range(C.rbegin(), C.rend())) {
return make_range(C.rbegin(), C.rend());
}
// Returns a std::reverse_iterator wrapped around the given iterator.
template <typename IteratorTy>
std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) {
return std::reverse_iterator<IteratorTy>(It);
}
// Returns an iterator_range over the given container which iterates in reverse.
// Note that the container must have begin()/end() methods which return
// bidirectional iterators for this to work.
template <typename ContainerTy>
auto reverse(
ContainerTy &&C,
typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr)
-> decltype(make_range(llvm::make_reverse_iterator(std::end(C)),
llvm::make_reverse_iterator(std::begin(C)))) {
return make_range(llvm::make_reverse_iterator(std::end(C)),
llvm::make_reverse_iterator(std::begin(C)));
}
//===----------------------------------------------------------------------===//
// Extra additions to <utility>
//===----------------------------------------------------------------------===//

View File

@ -44,6 +44,8 @@ public:
typedef Vector vector_type;
typedef typename vector_type::const_iterator iterator;
typedef typename vector_type::const_iterator const_iterator;
typedef typename vector_type::const_reverse_iterator reverse_iterator;
typedef typename vector_type::const_reverse_iterator const_reverse_iterator;
typedef typename vector_type::size_type size_type;
/// \brief Construct an empty SetVector
@ -85,6 +87,26 @@ public:
return vector_.end();
}
/// \brief Get an reverse_iterator to the end of the SetVector.
reverse_iterator rbegin() {
return vector_.rbegin();
}
/// \brief Get a const_reverse_iterator to the end of the SetVector.
const_reverse_iterator rbegin() const {
return vector_.rbegin();
}
/// \brief Get a reverse_iterator to the beginning of the SetVector.
reverse_iterator rend() {
return vector_.rend();
}
/// \brief Get a const_reverse_iterator to the beginning of the SetVector.
const_reverse_iterator rend() const {
return vector_.rend();
}
/// \brief Return the last element of the SetVector.
const T &back() const {
assert(!empty() && "Cannot call back() on empty SetVector!");

View File

@ -453,6 +453,9 @@ public:
// Assignment
SparseBitVector& operator=(const SparseBitVector& RHS) {
if (this == &RHS)
return *this;
Elements.clear();
ElementListConstIter ElementIter = RHS.Elements.begin();
@ -559,6 +562,9 @@ public:
// Union our bitmap with the RHS and return true if we changed.
bool operator|=(const SparseBitVector &RHS) {
if (this == &RHS)
return false;
bool changed = false;
ElementListIter Iter1 = Elements.begin();
ElementListConstIter Iter2 = RHS.Elements.begin();
@ -587,6 +593,9 @@ public:
// Intersect our bitmap with the RHS and return true if ours changed.
bool operator&=(const SparseBitVector &RHS) {
if (this == &RHS)
return false;
bool changed = false;
ElementListIter Iter1 = Elements.begin();
ElementListConstIter Iter2 = RHS.Elements.begin();
@ -619,9 +628,13 @@ public:
ElementListIter IterTmp = Iter1;
++Iter1;
Elements.erase(IterTmp);
changed = true;
}
}
Elements.erase(Iter1, Elements.end());
if (Iter1 != Elements.end()) {
Elements.erase(Iter1, Elements.end());
changed = true;
}
CurrElementIter = Elements.begin();
return changed;
}
@ -629,6 +642,14 @@ public:
// Intersect our bitmap with the complement of the RHS and return true
// if ours changed.
bool intersectWithComplement(const SparseBitVector &RHS) {
if (this == &RHS) {
if (!empty()) {
clear();
return true;
}
return false;
}
bool changed = false;
ElementListIter Iter1 = Elements.begin();
ElementListConstIter Iter2 = RHS.Elements.begin();
@ -675,6 +696,15 @@ public:
void intersectWithComplement(const SparseBitVector<ElementSize> &RHS1,
const SparseBitVector<ElementSize> &RHS2)
{
if (this == &RHS1) {
intersectWithComplement(RHS2);
return;
} else if (this == &RHS2) {
SparseBitVector RHS2Copy(RHS2);
intersectWithComplement(RHS1, RHS2Copy);
return;
}
Elements.clear();
CurrElementIter = Elements.begin();
ElementListConstIter Iter1 = RHS1.Elements.begin();

View File

@ -85,7 +85,9 @@ public:
spir64, // SPIR: standard portable IR for OpenCL 64-bit version
kalimba, // Kalimba: generic kalimba
shave, // SHAVE: Movidius vector VLIW processors
LastArchType = shave
wasm32, // WebAssembly with 32-bit pointers
wasm64, // WebAssembly with 64-bit pointers
LastArchType = wasm64
};
enum SubArchType {
NoSubArch,
@ -168,7 +170,8 @@ public:
MSVC,
Itanium,
Cygnus,
LastEnvironmentType = Cygnus
AMDOpenCL,
LastEnvironmentType = AMDOpenCL
};
enum ObjectFormatType {
UnknownObjectFormat,
@ -567,6 +570,22 @@ public:
/// architecture if no such variant can be found.
llvm::Triple get64BitArchVariant() const;
/// Form a triple with a big endian variant of the current architecture.
///
/// This can be used to move across "families" of architectures where useful.
///
/// \returns A new triple with a big endian architecture or an unknown
/// architecture if no such variant can be found.
llvm::Triple getBigEndianArchVariant() const;
/// Form a triple with a little endian variant of the current architecture.
///
/// This can be used to move across "families" of architectures where useful.
///
/// \returns A new triple with a little endian architecture or an unknown
/// architecture if no such variant can be found.
llvm::Triple getLittleEndianArchVariant() const;
/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
///
/// \param Arch the architecture name (e.g., "armv7s"). If it is an empty

View File

@ -50,50 +50,51 @@ unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
// http://en.wikipedia.org/wiki/Levenshtein_distance
//
// Although the algorithm is typically described using an m x n
// array, only two rows are used at a time, so this implementation
// just keeps two separate vectors for those two rows.
// array, only one row plus one element are used at a time, so this
// implementation just keeps one vector for the row. To update one entry,
// only the entries to the left, top, and top-left are needed. The left
// entry is in Row[x-1], the top entry is what's in Row[x] from the last
// iteration, and the top-left entry is stored in Previous.
typename ArrayRef<T>::size_type m = FromArray.size();
typename ArrayRef<T>::size_type n = ToArray.size();
const unsigned SmallBufferSize = 64;
unsigned SmallBuffer[SmallBufferSize];
std::unique_ptr<unsigned[]> Allocated;
unsigned *Previous = SmallBuffer;
if (2*(n + 1) > SmallBufferSize) {
Previous = new unsigned [2*(n+1)];
Allocated.reset(Previous);
unsigned *Row = SmallBuffer;
if (n + 1 > SmallBufferSize) {
Row = new unsigned[n + 1];
Allocated.reset(Row);
}
unsigned *Current = Previous + (n + 1);
for (unsigned i = 0; i <= n; ++i)
Previous[i] = i;
for (unsigned i = 1; i <= n; ++i)
Row[i] = i;
for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) {
Current[0] = y;
unsigned BestThisRow = Current[0];
Row[0] = y;
unsigned BestThisRow = Row[0];
unsigned Previous = y - 1;
for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) {
int OldRow = Row[x];
if (AllowReplacements) {
Current[x] = std::min(
Previous[x-1] + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
std::min(Current[x-1], Previous[x])+1);
Row[x] = std::min(
Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
std::min(Row[x-1], Row[x])+1);
}
else {
if (FromArray[y-1] == ToArray[x-1]) Current[x] = Previous[x-1];
else Current[x] = std::min(Current[x-1], Previous[x]) + 1;
if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous;
else Row[x] = std::min(Row[x-1], Row[x]) + 1;
}
BestThisRow = std::min(BestThisRow, Current[x]);
Previous = OldRow;
BestThisRow = std::min(BestThisRow, Row[x]);
}
if (MaxEditDistance && BestThisRow > MaxEditDistance)
return MaxEditDistance + 1;
unsigned *tmp = Current;
Current = Previous;
Previous = tmp;
}
unsigned Result = Previous[n];
unsigned Result = Row[n];
return Result;
}

View File

@ -162,6 +162,8 @@ protected:
int>::type = 0)
: I(std::forward<U &&>(u)) {}
const WrappedIteratorT &wrapped() const { return I; }
public:
typedef DifferenceTypeT difference_type;

View File

@ -20,6 +20,7 @@
#define LLVM_ADT_ITERATOR_RANGE_H
#include <utility>
#include <iterator>
namespace llvm {
@ -32,6 +33,12 @@ class iterator_range {
IteratorT begin_iterator, end_iterator;
public:
//TODO: Add SFINAE to test that the Container's iterators match the range's
// iterators.
template <typename Container>
iterator_range(Container &&c)
//TODO: Consider ADL/non-member begin/end calls.
: begin_iterator(c.begin()), end_iterator(c.end()) {}
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
: begin_iterator(std::move(begin_iterator)),
end_iterator(std::move(end_iterator)) {}
@ -51,6 +58,11 @@ template <class T> iterator_range<T> make_range(T x, T y) {
template <typename T> iterator_range<T> make_range(std::pair<T, T> p) {
return iterator_range<T>(std::move(p.first), std::move(p.second));
}
template<typename T>
iterator_range<decltype(begin(std::declval<T>()))> drop_begin(T &&t, int n) {
return make_range(std::next(begin(t), n), end(t));
}
}
#endif

View File

@ -16,11 +16,12 @@
// which automatically provides functionality for the entire suite of client
// APIs.
//
// This API identifies memory regions with the Location class. The pointer
// This API identifies memory regions with the MemoryLocation class. The pointer
// component specifies the base memory address of the region. The Size specifies
// the maximum size (in address units) of the memory region, or UnknownSize if
// the size is not known. The TBAA tag identifies the "type" of the memory
// reference; see the TypeBasedAliasAnalysis class for details.
// the maximum size (in address units) of the memory region, or
// MemoryLocation::UnknownSize if the size is not known. The TBAA tag
// identifies the "type" of the memory reference; see the
// TypeBasedAliasAnalysis class for details.
//
// Some non-obvious details include:
// - Pointers that point to two completely different objects in memory never
@ -54,6 +55,106 @@ class AnalysisUsage;
class MemTransferInst;
class MemIntrinsic;
class DominatorTree;
class OrderedBasicBlock;
/// The possible results of an alias query.
///
/// These results are always computed between two MemoryLocation objects as
/// a query to some alias analysis.
///
/// Note that these are unscoped enumerations because we would like to support
/// implicitly testing a result for the existence of any possible aliasing with
/// a conversion to bool, but an "enum class" doesn't support this. The
/// canonical names from the literature are suffixed and unique anyways, and so
/// they serve as global constants in LLVM for these results.
///
/// See docs/AliasAnalysis.html for more information on the specific meanings
/// of these values.
enum AliasResult {
/// The two locations do not alias at all.
///
/// This value is arranged to convert to false, while all other values
/// convert to true. This allows a boolean context to convert the result to
/// a binary flag indicating whether there is the possibility of aliasing.
NoAlias = 0,
/// The two locations may or may not alias. This is the least precise result.
MayAlias,
/// The two locations alias, but only due to a partial overlap.
PartialAlias,
/// The two locations precisely alias each other.
MustAlias,
};
/// Flags indicating whether a memory access modifies or references memory.
///
/// This is no access at all, a modification, a reference, or both
/// a modification and a reference. These are specifically structured such that
/// they form a two bit matrix and bit-tests for 'mod' or 'ref' work with any
/// of the possible values.
enum ModRefInfo {
/// The access neither references nor modifies the value stored in memory.
MRI_NoModRef = 0,
/// The access references the value stored in memory.
MRI_Ref = 1,
/// The access modifies the value stored in memory.
MRI_Mod = 2,
/// The access both references and modifies the value stored in memory.
MRI_ModRef = MRI_Ref | MRI_Mod
};
/// The locations at which a function might access memory.
///
/// These are primarily used in conjunction with the \c AccessKind bits to
/// describe both the nature of access and the locations of access for a
/// function call.
enum FunctionModRefLocation {
/// Base case is no access to memory.
FMRL_Nowhere = 0,
/// Access to memory via argument pointers.
FMRL_ArgumentPointees = 4,
/// Access to any memory.
FMRL_Anywhere = 8 | FMRL_ArgumentPointees
};
/// Summary of how a function affects memory in the program.
///
/// Loads from constant globals are not considered memory accesses for this
/// interface. Also, functions may freely modify stack space local to their
/// invocation without having to report it through these interfaces.
enum FunctionModRefBehavior {
/// This function does not perform any non-local loads or stores to memory.
///
/// This property corresponds to the GCC 'const' attribute.
/// This property corresponds to the LLVM IR 'readnone' attribute.
/// This property corresponds to the IntrNoMem LLVM intrinsic flag.
FMRB_DoesNotAccessMemory = FMRL_Nowhere | MRI_NoModRef,
/// The only memory references in this function (if it has any) are
/// non-volatile loads from objects pointed to by its pointer-typed
/// arguments, with arbitrary offsets.
///
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
FMRB_OnlyReadsArgumentPointees = FMRL_ArgumentPointees | MRI_Ref,
/// The only memory references in this function (if it has any) are
/// non-volatile loads and stores from objects pointed to by its
/// pointer-typed arguments, with arbitrary offsets.
///
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
FMRB_OnlyAccessesArgumentPointees = FMRL_ArgumentPointees | MRI_ModRef,
/// This function does not perform any non-local stores or volatile loads,
/// but may read from any memory location.
///
/// This property corresponds to the GCC 'pure' attribute.
/// This property corresponds to the LLVM IR 'readonly' attribute.
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
FMRB_OnlyReadsMemory = FMRL_Anywhere | MRI_Ref,
/// This indicates that the function could not be classified into one of the
/// behaviors above.
FMRB_UnknownModRefBehavior = FMRL_Anywhere | MRI_ModRef
};
class AliasAnalysis {
protected:
@ -80,11 +181,6 @@ public:
AliasAnalysis() : DL(nullptr), TLI(nullptr), AA(nullptr) {}
virtual ~AliasAnalysis(); // We want to be subclassed
/// UnknownSize - This is a special value which can be used with the
/// size arguments in alias queries to indicate that the caller does not
/// know the sizes of the potential memory references.
static uint64_t const UnknownSize = MemoryLocation::UnknownSize;
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
/// object, or null if no TargetLibraryInfo object is available.
///
@ -96,242 +192,284 @@ public:
uint64_t getTypeStoreSize(Type *Ty);
//===--------------------------------------------------------------------===//
/// Alias Queries...
///
/// \name Alias Queries
/// @{
/// Legacy typedef for the AA location object. New code should use \c
/// MemoryLocation directly.
typedef MemoryLocation Location;
/// Alias analysis result - Either we know for sure that it does not alias, we
/// know for sure it must alias, or we don't know anything: The two pointers
/// _might_ alias. This enum is designed so you can do things like:
/// if (AA.alias(P1, P2)) { ... }
/// to check to see if two pointers might alias.
///
/// See docs/AliasAnalysis.html for more information on the specific meanings
/// of these values.
///
enum AliasResult {
NoAlias = 0, ///< No dependencies.
MayAlias, ///< Anything goes.
PartialAlias, ///< Pointers differ, but pointees overlap.
MustAlias ///< Pointers are equal.
};
/// alias - The main low level interface to the alias analysis implementation.
/// The main low level interface to the alias analysis implementation.
/// Returns an AliasResult indicating whether the two pointers are aliased to
/// each other. This is the interface that must be implemented by specific
/// each other. This is the interface that must be implemented by specific
/// alias analysis implementations.
virtual AliasResult alias(const Location &LocA, const Location &LocB);
virtual AliasResult alias(const MemoryLocation &LocA,
const MemoryLocation &LocB);
/// alias - A convenience wrapper.
AliasResult alias(const Value *V1, uint64_t V1Size,
const Value *V2, uint64_t V2Size) {
return alias(Location(V1, V1Size), Location(V2, V2Size));
/// A convenience wrapper around the primary \c alias interface.
AliasResult alias(const Value *V1, uint64_t V1Size, const Value *V2,
uint64_t V2Size) {
return alias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size));
}
/// alias - A convenience wrapper.
/// A convenience wrapper around the primary \c alias interface.
AliasResult alias(const Value *V1, const Value *V2) {
return alias(V1, UnknownSize, V2, UnknownSize);
return alias(V1, MemoryLocation::UnknownSize, V2,
MemoryLocation::UnknownSize);
}
/// isNoAlias - A trivial helper function to check to see if the specified
/// pointers are no-alias.
bool isNoAlias(const Location &LocA, const Location &LocB) {
/// A trivial helper function to check to see if the specified pointers are
/// no-alias.
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
return alias(LocA, LocB) == NoAlias;
}
/// isNoAlias - A convenience wrapper.
bool isNoAlias(const Value *V1, uint64_t V1Size,
const Value *V2, uint64_t V2Size) {
return isNoAlias(Location(V1, V1Size), Location(V2, V2Size));
/// A convenience wrapper around the \c isNoAlias helper interface.
bool isNoAlias(const Value *V1, uint64_t V1Size, const Value *V2,
uint64_t V2Size) {
return isNoAlias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size));
}
/// isNoAlias - A convenience wrapper.
/// A convenience wrapper around the \c isNoAlias helper interface.
bool isNoAlias(const Value *V1, const Value *V2) {
return isNoAlias(Location(V1), Location(V2));
return isNoAlias(MemoryLocation(V1), MemoryLocation(V2));
}
/// isMustAlias - A convenience wrapper.
bool isMustAlias(const Location &LocA, const Location &LocB) {
/// A trivial helper function to check to see if the specified pointers are
/// must-alias.
bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
return alias(LocA, LocB) == MustAlias;
}
/// isMustAlias - A convenience wrapper.
/// A convenience wrapper around the \c isMustAlias helper interface.
bool isMustAlias(const Value *V1, const Value *V2) {
return alias(V1, 1, V2, 1) == MustAlias;
}
/// pointsToConstantMemory - If the specified memory location is
/// known to be constant, return true. If OrLocal is true and the
/// specified memory location is known to be "local" (derived from
/// an alloca), return true. Otherwise return false.
virtual bool pointsToConstantMemory(const Location &Loc,
/// Checks whether the given location points to constant memory, or if
/// \p OrLocal is true whether it points to a local alloca.
virtual bool pointsToConstantMemory(const MemoryLocation &Loc,
bool OrLocal = false);
/// pointsToConstantMemory - A convenient wrapper.
/// A convenience wrapper around the primary \c pointsToConstantMemory
/// interface.
bool pointsToConstantMemory(const Value *P, bool OrLocal = false) {
return pointsToConstantMemory(Location(P), OrLocal);
return pointsToConstantMemory(MemoryLocation(P), OrLocal);
}
/// @}
//===--------------------------------------------------------------------===//
/// Simple mod/ref information...
/// \name Simple mod/ref information
/// @{
/// Get the ModRef info associated with a pointer argument of a callsite. The
/// result's bits are set to indicate the allowed aliasing ModRef kinds. Note
/// that these bits do not necessarily account for the overall behavior of
/// the function, but rather only provide additional per-argument
/// information.
virtual ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
/// Return the behavior of the given call site.
virtual FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
/// Return the behavior when calling the given function.
virtual FunctionModRefBehavior getModRefBehavior(const Function *F);
/// Checks if the specified call is known to never read or write memory.
///
/// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are
/// bits which may be or'd together.
///
enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 };
/// These values define additional bits used to define the
/// ModRefBehavior values.
enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees };
/// ModRefBehavior - Summary of how a function affects memory in the program.
/// Loads from constant globals are not considered memory accesses for this
/// interface. Also, functions may freely modify stack space local to their
/// invocation without having to report it through these interfaces.
enum ModRefBehavior {
/// DoesNotAccessMemory - This function does not perform any non-local loads
/// or stores to memory.
///
/// This property corresponds to the GCC 'const' attribute.
/// This property corresponds to the LLVM IR 'readnone' attribute.
/// This property corresponds to the IntrNoMem LLVM intrinsic flag.
DoesNotAccessMemory = Nowhere | NoModRef,
/// OnlyReadsArgumentPointees - The only memory references in this function
/// (if it has any) are non-volatile loads from objects pointed to by its
/// pointer-typed arguments, with arbitrary offsets.
///
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
OnlyReadsArgumentPointees = ArgumentPointees | Ref,
/// OnlyAccessesArgumentPointees - The only memory references in this
/// function (if it has any) are non-volatile loads and stores from objects
/// pointed to by its pointer-typed arguments, with arbitrary offsets.
///
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
OnlyAccessesArgumentPointees = ArgumentPointees | ModRef,
/// OnlyReadsMemory - This function does not perform any non-local stores or
/// volatile loads, but may read from any memory location.
///
/// This property corresponds to the GCC 'pure' attribute.
/// This property corresponds to the LLVM IR 'readonly' attribute.
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
OnlyReadsMemory = Anywhere | Ref,
/// UnknownModRefBehavior - This indicates that the function could not be
/// classified into one of the behaviors above.
UnknownModRefBehavior = Anywhere | ModRef
};
/// Get the location associated with a pointer argument of a callsite.
/// The mask bits are set to indicate the allowed aliasing ModRef kinds.
/// Note that these mask bits do not necessarily account for the overall
/// behavior of the function, but rather only provide additional
/// per-argument information.
virtual Location getArgLocation(ImmutableCallSite CS, unsigned ArgIdx,
ModRefResult &Mask);
/// getModRefBehavior - Return the behavior when calling the given call site.
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
/// getModRefBehavior - Return the behavior when calling the given function.
/// For use when the call site is not known.
virtual ModRefBehavior getModRefBehavior(const Function *F);
/// doesNotAccessMemory - If the specified call is known to never read or
/// write memory, return true. If the call only reads from known-constant
/// memory, it is also legal to return true. Calls that unwind the stack
/// are legal for this predicate.
/// Note that if the call only reads from known-constant memory, it is also
/// legal to return true. Also, calls that unwind the stack are legal for
/// this predicate.
///
/// Many optimizations (such as CSE and LICM) can be performed on such calls
/// without worrying about aliasing properties, and many calls have this
/// property (e.g. calls to 'sin' and 'cos').
///
/// This property corresponds to the GCC 'const' attribute.
///
bool doesNotAccessMemory(ImmutableCallSite CS) {
return getModRefBehavior(CS) == DoesNotAccessMemory;
return getModRefBehavior(CS) == FMRB_DoesNotAccessMemory;
}
/// doesNotAccessMemory - If the specified function is known to never read or
/// write memory, return true. For use when the call site is not known.
/// Checks if the specified function is known to never read or write memory.
///
/// Note that if the function only reads from known-constant memory, it is
/// also legal to return true. Also, function that unwind the stack are legal
/// for this predicate.
///
/// Many optimizations (such as CSE and LICM) can be performed on such calls
/// to such functions without worrying about aliasing properties, and many
/// functions have this property (e.g. 'sin' and 'cos').
///
/// This property corresponds to the GCC 'const' attribute.
bool doesNotAccessMemory(const Function *F) {
return getModRefBehavior(F) == DoesNotAccessMemory;
return getModRefBehavior(F) == FMRB_DoesNotAccessMemory;
}
/// onlyReadsMemory - If the specified call is known to only read from
/// non-volatile memory (or not access memory at all), return true. Calls
/// that unwind the stack are legal for this predicate.
/// Checks if the specified call is known to only read from non-volatile
/// memory (or not access memory at all).
///
/// Calls that unwind the stack are legal for this predicate.
///
/// This property allows many common optimizations to be performed in the
/// absence of interfering store instructions, such as CSE of strlen calls.
///
/// This property corresponds to the GCC 'pure' attribute.
///
bool onlyReadsMemory(ImmutableCallSite CS) {
return onlyReadsMemory(getModRefBehavior(CS));
}
/// onlyReadsMemory - If the specified function is known to only read from
/// non-volatile memory (or not access memory at all), return true. For use
/// when the call site is not known.
/// Checks if the specified function is known to only read from non-volatile
/// memory (or not access memory at all).
///
/// Functions that unwind the stack are legal for this predicate.
///
/// This property allows many common optimizations to be performed in the
/// absence of interfering store instructions, such as CSE of strlen calls.
///
/// This property corresponds to the GCC 'pure' attribute.
bool onlyReadsMemory(const Function *F) {
return onlyReadsMemory(getModRefBehavior(F));
}
/// onlyReadsMemory - Return true if functions with the specified behavior are
/// known to only read from non-volatile memory (or not access memory at all).
///
static bool onlyReadsMemory(ModRefBehavior MRB) {
return !(MRB & Mod);
/// Checks if functions with the specified behavior are known to only read
/// from non-volatile memory (or not access memory at all).
static bool onlyReadsMemory(FunctionModRefBehavior MRB) {
return !(MRB & MRI_Mod);
}
/// onlyAccessesArgPointees - Return true if functions with the specified
/// behavior are known to read and write at most from objects pointed to by
/// their pointer-typed arguments (with arbitrary offsets).
///
static bool onlyAccessesArgPointees(ModRefBehavior MRB) {
return !(MRB & Anywhere & ~ArgumentPointees);
/// Checks if functions with the specified behavior are known to read and
/// write at most from objects pointed to by their pointer-typed arguments
/// (with arbitrary offsets).
static bool onlyAccessesArgPointees(FunctionModRefBehavior MRB) {
return !(MRB & FMRL_Anywhere & ~FMRL_ArgumentPointees);
}
/// doesAccessArgPointees - Return true if functions with the specified
/// behavior are known to potentially read or write from objects pointed
/// to be their pointer-typed arguments (with arbitrary offsets).
///
static bool doesAccessArgPointees(ModRefBehavior MRB) {
return (MRB & ModRef) && (MRB & ArgumentPointees);
/// Checks if functions with the specified behavior are known to potentially
/// read or write from objects pointed to be their pointer-typed arguments
/// (with arbitrary offsets).
static bool doesAccessArgPointees(FunctionModRefBehavior MRB) {
return (MRB & MRI_ModRef) && (MRB & FMRL_ArgumentPointees);
}
/// getModRefInfo - Return information about whether or not an
/// instruction may read or write memory (without regard to a
/// specific location)
ModRefResult getModRefInfo(const Instruction *I) {
/// getModRefInfo (for call sites) - Return information about whether
/// a particular call site modifies or reads the specified memory location.
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS,
const MemoryLocation &Loc);
/// getModRefInfo (for call sites) - A convenience wrapper.
ModRefInfo getModRefInfo(ImmutableCallSite CS, const Value *P,
uint64_t Size) {
return getModRefInfo(CS, MemoryLocation(P, Size));
}
/// getModRefInfo (for calls) - Return information about whether
/// a particular call modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const CallInst *C, const MemoryLocation &Loc) {
return getModRefInfo(ImmutableCallSite(C), Loc);
}
/// getModRefInfo (for calls) - A convenience wrapper.
ModRefInfo getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) {
return getModRefInfo(C, MemoryLocation(P, Size));
}
/// getModRefInfo (for invokes) - Return information about whether
/// a particular invoke modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const InvokeInst *I, const MemoryLocation &Loc) {
return getModRefInfo(ImmutableCallSite(I), Loc);
}
/// getModRefInfo (for invokes) - A convenience wrapper.
ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P, uint64_t Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
}
/// getModRefInfo (for loads) - Return information about whether
/// a particular load modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc);
/// getModRefInfo (for loads) - A convenience wrapper.
ModRefInfo getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) {
return getModRefInfo(L, MemoryLocation(P, Size));
}
/// getModRefInfo (for stores) - Return information about whether
/// a particular store modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc);
/// getModRefInfo (for stores) - A convenience wrapper.
ModRefInfo getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size) {
return getModRefInfo(S, MemoryLocation(P, Size));
}
/// getModRefInfo (for fences) - Return information about whether
/// a particular store modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) {
// Conservatively correct. (We could possibly be a bit smarter if
// Loc is a alloca that doesn't escape.)
return MRI_ModRef;
}
/// getModRefInfo (for fences) - A convenience wrapper.
ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size) {
return getModRefInfo(S, MemoryLocation(P, Size));
}
/// getModRefInfo (for cmpxchges) - Return information about whether
/// a particular cmpxchg modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX,
const MemoryLocation &Loc);
/// getModRefInfo (for cmpxchges) - A convenience wrapper.
ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, const Value *P,
unsigned Size) {
return getModRefInfo(CX, MemoryLocation(P, Size));
}
/// getModRefInfo (for atomicrmws) - Return information about whether
/// a particular atomicrmw modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc);
/// getModRefInfo (for atomicrmws) - A convenience wrapper.
ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const Value *P,
unsigned Size) {
return getModRefInfo(RMW, MemoryLocation(P, Size));
}
/// getModRefInfo (for va_args) - Return information about whether
/// a particular va_arg modifies or reads the specified memory location.
ModRefInfo getModRefInfo(const VAArgInst *I, const MemoryLocation &Loc);
/// getModRefInfo (for va_args) - A convenience wrapper.
ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P, uint64_t Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
}
/// Check whether or not an instruction may read or write memory (without
/// regard to a specific location).
///
/// For function calls, this delegates to the alias-analysis specific
/// call-site mod-ref behavior queries. Otherwise it delegates to the generic
/// mod ref information query without a location.
ModRefInfo getModRefInfo(const Instruction *I) {
if (auto CS = ImmutableCallSite(I)) {
auto MRB = getModRefBehavior(CS);
if (MRB & ModRef)
return ModRef;
else if (MRB & Ref)
return Ref;
else if (MRB & Mod)
return Mod;
return NoModRef;
if (MRB & MRI_ModRef)
return MRI_ModRef;
else if (MRB & MRI_Ref)
return MRI_Ref;
else if (MRB & MRI_Mod)
return MRI_Mod;
return MRI_NoModRef;
}
return getModRefInfo(I, Location());
return getModRefInfo(I, MemoryLocation());
}
/// getModRefInfo - Return information about whether or not an instruction may
/// read or write the specified memory location. An instruction
/// that doesn't read or write memory may be trivially LICM'd for example.
ModRefResult getModRefInfo(const Instruction *I,
const Location &Loc) {
/// Check whether or not an instruction may read or write the specified
/// memory location.
///
/// An instruction that doesn't read or write memory may be trivially LICM'd
/// for example.
///
/// This primarily delegates to specific helpers above.
ModRefInfo getModRefInfo(const Instruction *I, const MemoryLocation &Loc) {
switch (I->getOpcode()) {
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc);
case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc);
@ -343,201 +481,71 @@ public:
return getModRefInfo((const AtomicRMWInst*)I, Loc);
case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc);
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
default: return NoModRef;
default:
return MRI_NoModRef;
}
}
/// getModRefInfo - A convenience wrapper.
ModRefResult getModRefInfo(const Instruction *I,
const Value *P, uint64_t Size) {
return getModRefInfo(I, Location(P, Size));
/// A convenience wrapper for constructing the memory location.
ModRefInfo getModRefInfo(const Instruction *I, const Value *P,
uint64_t Size) {
return getModRefInfo(I, MemoryLocation(P, Size));
}
/// getModRefInfo (for call sites) - Return information about whether
/// a particular call site modifies or reads the specified memory location.
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
const Location &Loc);
/// Return information about whether a call and an instruction may refer to
/// the same memory locations.
ModRefInfo getModRefInfo(Instruction *I, ImmutableCallSite Call);
/// getModRefInfo (for call sites) - A convenience wrapper.
ModRefResult getModRefInfo(ImmutableCallSite CS,
const Value *P, uint64_t Size) {
return getModRefInfo(CS, Location(P, Size));
}
/// getModRefInfo (for calls) - Return information about whether
/// a particular call modifies or reads the specified memory location.
ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) {
return getModRefInfo(ImmutableCallSite(C), Loc);
}
/// getModRefInfo (for calls) - A convenience wrapper.
ModRefResult getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) {
return getModRefInfo(C, Location(P, Size));
}
/// getModRefInfo (for invokes) - Return information about whether
/// a particular invoke modifies or reads the specified memory location.
ModRefResult getModRefInfo(const InvokeInst *I,
const Location &Loc) {
return getModRefInfo(ImmutableCallSite(I), Loc);
}
/// getModRefInfo (for invokes) - A convenience wrapper.
ModRefResult getModRefInfo(const InvokeInst *I,
const Value *P, uint64_t Size) {
return getModRefInfo(I, Location(P, Size));
}
/// getModRefInfo (for loads) - Return information about whether
/// a particular load modifies or reads the specified memory location.
ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc);
/// getModRefInfo (for loads) - A convenience wrapper.
ModRefResult getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) {
return getModRefInfo(L, Location(P, Size));
}
/// getModRefInfo (for stores) - Return information about whether
/// a particular store modifies or reads the specified memory location.
ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc);
/// getModRefInfo (for stores) - A convenience wrapper.
ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){
return getModRefInfo(S, Location(P, Size));
}
/// getModRefInfo (for fences) - Return information about whether
/// a particular store modifies or reads the specified memory location.
ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) {
// Conservatively correct. (We could possibly be a bit smarter if
// Loc is a alloca that doesn't escape.)
return ModRef;
}
/// getModRefInfo (for fences) - A convenience wrapper.
ModRefResult getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size){
return getModRefInfo(S, Location(P, Size));
}
/// getModRefInfo (for cmpxchges) - Return information about whether
/// a particular cmpxchg modifies or reads the specified memory location.
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc);
/// getModRefInfo (for cmpxchges) - A convenience wrapper.
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX,
const Value *P, unsigned Size) {
return getModRefInfo(CX, Location(P, Size));
}
/// getModRefInfo (for atomicrmws) - Return information about whether
/// a particular atomicrmw modifies or reads the specified memory location.
ModRefResult getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc);
/// getModRefInfo (for atomicrmws) - A convenience wrapper.
ModRefResult getModRefInfo(const AtomicRMWInst *RMW,
const Value *P, unsigned Size) {
return getModRefInfo(RMW, Location(P, Size));
}
/// getModRefInfo (for va_args) - Return information about whether
/// a particular va_arg modifies or reads the specified memory location.
ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc);
/// getModRefInfo (for va_args) - A convenience wrapper.
ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){
return getModRefInfo(I, Location(P, Size));
}
/// getModRefInfo - Return information about whether a call and an instruction
/// may refer to the same memory locations.
ModRefResult getModRefInfo(Instruction *I,
ImmutableCallSite Call);
/// getModRefInfo - Return information about whether two call sites may refer
/// to the same set of memory locations. See
/// Return information about whether two call sites may refer to the same set
/// of memory locations. See the AA documentation for details:
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
/// for details.
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2);
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2);
/// callCapturesBefore - Return information about whether a particular call
/// site modifies or reads the specified memory location.
ModRefResult callCapturesBefore(const Instruction *I,
const AliasAnalysis::Location &MemLoc,
DominatorTree *DT);
/// \brief Return information about whether a particular call site modifies
/// or reads the specified memory location \p MemLoc before instruction \p I
/// in a BasicBlock. A ordered basic block \p OBB can be used to speed up
/// instruction ordering queries inside the BasicBlock containing \p I.
ModRefInfo callCapturesBefore(const Instruction *I,
const MemoryLocation &MemLoc, DominatorTree *DT,
OrderedBasicBlock *OBB = nullptr);
/// callCapturesBefore - A convenience wrapper.
ModRefResult callCapturesBefore(const Instruction *I, const Value *P,
uint64_t Size, DominatorTree *DT) {
return callCapturesBefore(I, Location(P, Size), DT);
/// \brief A convenience wrapper to synthesize a memory location.
ModRefInfo callCapturesBefore(const Instruction *I, const Value *P,
uint64_t Size, DominatorTree *DT,
OrderedBasicBlock *OBB = nullptr) {
return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB);
}
/// @}
//===--------------------------------------------------------------------===//
/// Higher level methods for querying mod/ref information.
///
/// \name Higher level methods for querying mod/ref information.
/// @{
/// canBasicBlockModify - Return true if it is possible for execution of the
/// specified basic block to modify the location Loc.
bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc);
/// Check if it is possible for execution of the specified basic block to
/// modify the location Loc.
bool canBasicBlockModify(const BasicBlock &BB, const MemoryLocation &Loc);
/// canBasicBlockModify - A convenience wrapper.
bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){
return canBasicBlockModify(BB, Location(P, Size));
/// A convenience wrapper synthesizing a memory location.
bool canBasicBlockModify(const BasicBlock &BB, const Value *P,
uint64_t Size) {
return canBasicBlockModify(BB, MemoryLocation(P, Size));
}
/// canInstructionRangeModRef - Return true if it is possible for the
/// execution of the specified instructions to mod\ref (according to the
/// mode) the location Loc. The instructions to consider are all
/// of the instructions in the range of [I1,I2] INCLUSIVE.
/// I1 and I2 must be in the same basic block.
bool canInstructionRangeModRef(const Instruction &I1,
const Instruction &I2, const Location &Loc,
const ModRefResult Mode);
/// canInstructionRangeModRef - A convenience wrapper.
bool canInstructionRangeModRef(const Instruction &I1,
const Instruction &I2, const Value *Ptr,
uint64_t Size, const ModRefResult Mode) {
return canInstructionRangeModRef(I1, I2, Location(Ptr, Size), Mode);
}
//===--------------------------------------------------------------------===//
/// Methods that clients should call when they transform the program to allow
/// alias analyses to update their internal data structures. Note that these
/// methods may be called on any instruction, regardless of whether or not
/// they have pointer-analysis implications.
/// Check if it is possible for the execution of the specified instructions
/// to mod\ref (according to the mode) the location Loc.
///
/// The instructions to consider are all of the instructions in the range of
/// [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block.
bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2,
const MemoryLocation &Loc,
const ModRefInfo Mode);
/// deleteValue - This method should be called whenever an LLVM Value is
/// deleted from the program, for example when an instruction is found to be
/// redundant and is eliminated.
///
virtual void deleteValue(Value *V);
/// copyValue - This method should be used whenever a preexisting value in the
/// program is copied or cloned, introducing a new value. Note that analysis
/// implementations should tolerate clients that use this method to introduce
/// the same value multiple times: if the analysis already knows about a
/// value, it should ignore the request.
///
virtual void copyValue(Value *From, Value *To);
/// addEscapingUse - This method should be used whenever an escaping use is
/// added to a pointer value. Analysis implementations may either return
/// conservative responses for that value in the future, or may recompute
/// some or all internal state to continue providing precise responses.
///
/// Escaping uses are considered by anything _except_ the following:
/// - GEPs or bitcasts of the pointer
/// - Loads through the pointer
/// - Stores through (but not of) the pointer
virtual void addEscapingUse(Use &U);
/// replaceWithNewValue - This method is the obvious combination of the two
/// above, and it provided as a helper to simplify client code.
///
void replaceWithNewValue(Value *Old, Value *New) {
copyValue(Old, New);
deleteValue(Old);
/// A convenience wrapper synthesizing a memory location.
bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2,
const Value *Ptr, uint64_t Size,
const ModRefInfo Mode) {
return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode);
}
};

View File

@ -117,24 +117,30 @@ class AliasSet : public ilist_node<AliasSet> {
// AliasSets forwarding to it.
unsigned RefCount : 28;
/// AccessType - Keep track of whether this alias set merely refers to the
/// locations of memory, whether it modifies the memory, or whether it does
/// both. The lattice goes from "NoModRef" to either Refs or Mods, then to
/// ModRef as necessary.
/// The kinds of access this alias set models.
///
enum AccessType {
NoModRef = 0, Refs = 1, // Ref = bit 1
Mods = 2, ModRef = 3 // Mod = bit 2
/// We keep track of whether this alias set merely refers to the locations of
/// memory (and not any particular access), whether it modifies or references
/// the memory, or whether it does both. The lattice goes from "NoAccess" to
/// either RefAccess or ModAccess, then to ModRefAccess as necessary.
enum AccessLattice {
NoAccess = 0,
RefAccess = 1,
ModAccess = 2,
ModRefAccess = RefAccess | ModAccess
};
unsigned AccessTy : 2;
unsigned Access : 2;
/// AliasType - Keep track the relationships between the pointers in the set.
/// Lattice goes from MustAlias to MayAlias.
/// The kind of alias relationship between pointers of the set.
///
enum AliasType {
MustAlias = 0, MayAlias = 1
/// These represent conservatively correct alias results between any members
/// of the set. We represent these independently of the values of alias
/// results in order to pack it into a single bit. Lattice goes from
/// MustAlias to MayAlias.
enum AliasLattice {
SetMustAlias = 0, SetMayAlias = 1
};
unsigned AliasTy : 1;
unsigned Alias : 1;
// Volatile - True if this alias set contains volatile loads or stores.
bool Volatile : 1;
@ -153,10 +159,10 @@ class AliasSet : public ilist_node<AliasSet> {
public:
/// Accessors...
bool isRef() const { return AccessTy & Refs; }
bool isMod() const { return AccessTy & Mods; }
bool isMustAlias() const { return AliasTy == MustAlias; }
bool isMayAlias() const { return AliasTy == MayAlias; }
bool isRef() const { return Access & RefAccess; }
bool isMod() const { return Access & ModAccess; }
bool isMustAlias() const { return Alias == SetMustAlias; }
bool isMayAlias() const { return Alias == SetMayAlias; }
// isVolatile - Return true if this alias set contains volatile loads or
// stores.
@ -218,7 +224,7 @@ private:
friend struct ilist_sentinel_traits<AliasSet>;
AliasSet()
: PtrList(nullptr), PtrListEnd(&PtrList), Forward(nullptr), RefCount(0),
AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
Access(NoAccess), Alias(SetMustAlias), Volatile(false) {
}
AliasSet(const AliasSet &AS) = delete;
@ -419,11 +425,11 @@ private:
}
AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo,
AliasSet::AccessType E,
AliasSet::AccessLattice E,
bool &NewSet) {
NewSet = false;
AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet);
AS.AccessTy |= E;
AS.Access |= E;
return AS;
}
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,

View File

@ -66,7 +66,7 @@ public:
/// \brief Add an @llvm.assume intrinsic to this function's cache.
///
/// The call passed in must be an instruction within this fuction and must
/// The call passed in must be an instruction within this function and must
/// not already be in the cache.
void registerAssumption(CallInst *CI);
@ -79,7 +79,7 @@ public:
}
/// \brief Access the list of assumption handles currently tracked for this
/// fuction.
/// function.
///
/// Note that these produce weak handles that may be null. The caller must
/// handle that case.

View File

@ -21,26 +21,20 @@
namespace llvm {
class BranchProbabilityInfo;
class LoopInfo;
template <class BlockT> class BlockFrequencyInfoImpl;
/// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to
/// estimate IR basic block frequencies.
class BlockFrequencyInfo : public FunctionPass {
class BlockFrequencyInfo {
typedef BlockFrequencyInfoImpl<BasicBlock> ImplType;
std::unique_ptr<ImplType> BFI;
public:
static char ID;
BlockFrequencyInfo();
BlockFrequencyInfo(const Function &F, const BranchProbabilityInfo &BPI,
const LoopInfo &LI);
~BlockFrequencyInfo() override;
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void print(raw_ostream &O, const Module *M) const override;
const Function *getFunction() const;
void view() const;
@ -51,6 +45,10 @@ public:
/// floating points.
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
/// calculate - compute block frequency info for the given function.
void calculate(const Function &F, const BranchProbabilityInfo &BPI,
const LoopInfo &LI);
// Print the block frequency Freq to OS using the current functions entry
// frequency to convert freq into a relative decimal form.
raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const;
@ -60,7 +58,28 @@ public:
raw_ostream &printBlockFreq(raw_ostream &OS, const BasicBlock *BB) const;
uint64_t getEntryFreq() const;
void releaseMemory();
void print(raw_ostream &OS) const;
};
/// \brief Legacy analysis pass which computes \c BlockFrequencyInfo.
class BlockFrequencyInfoWrapperPass : public FunctionPass {
BlockFrequencyInfo BFI;
public:
static char ID;
BlockFrequencyInfoWrapperPass();
~BlockFrequencyInfoWrapperPass() override;
BlockFrequencyInfo &getBFI() { return BFI; }
const BlockFrequencyInfo &getBFI() const { return BFI; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M) const override;
};
}

View File

@ -196,23 +196,26 @@ public:
struct LoopData {
typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap;
typedef SmallVector<BlockNode, 4> NodeList;
LoopData *Parent; ///< The parent loop.
bool IsPackaged; ///< Whether this has been packaged.
uint32_t NumHeaders; ///< Number of headers.
ExitMap Exits; ///< Successor edges (and weights).
NodeList Nodes; ///< Header and the members of the loop.
BlockMass BackedgeMass; ///< Mass returned to loop header.
typedef SmallVector<BlockMass, 1> HeaderMassList;
LoopData *Parent; ///< The parent loop.
bool IsPackaged; ///< Whether this has been packaged.
uint32_t NumHeaders; ///< Number of headers.
ExitMap Exits; ///< Successor edges (and weights).
NodeList Nodes; ///< Header and the members of the loop.
HeaderMassList BackedgeMass; ///< Mass returned to each loop header.
BlockMass Mass;
Scaled64 Scale;
LoopData(LoopData *Parent, const BlockNode &Header)
: Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header) {}
: Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header),
BackedgeMass(1) {}
template <class It1, class It2>
LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther,
It2 LastOther)
: Parent(Parent), IsPackaged(false), Nodes(FirstHeader, LastHeader) {
NumHeaders = Nodes.size();
Nodes.insert(Nodes.end(), FirstOther, LastOther);
BackedgeMass.resize(NumHeaders);
}
bool isHeader(const BlockNode &Node) const {
if (isIrreducible())
@ -223,6 +226,14 @@ public:
BlockNode getHeader() const { return Nodes[0]; }
bool isIrreducible() const { return NumHeaders > 1; }
HeaderMassList::difference_type getHeaderIndex(const BlockNode &B) {
assert(isHeader(B) && "this is only valid on loop header blocks");
if (isIrreducible())
return std::lower_bound(Nodes.begin(), Nodes.begin() + NumHeaders, B) -
Nodes.begin();
return 0;
}
NodeList::const_iterator members_begin() const {
return Nodes.begin() + NumHeaders;
}
@ -431,6 +442,16 @@ public:
/// \brief Compute the loop scale for a loop.
void computeLoopScale(LoopData &Loop);
/// Adjust the mass of all headers in an irreducible loop.
///
/// Initially, irreducible loops are assumed to distribute their mass
/// equally among its headers. This can lead to wrong frequency estimates
/// since some headers may be executed more frequently than others.
///
/// This adjusts header mass distribution so it matches the weights of
/// the backedges going into each of the loop headers.
void adjustLoopHeaderMass(LoopData &Loop);
/// \brief Package up a loop.
void packageLoop(LoopData &Loop);
@ -695,6 +716,17 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
/// - Distribute the mass accordingly, dithering to minimize mass loss,
/// as described in \a distributeMass().
///
/// In the case of irreducible loops, instead of a single loop header,
/// there will be several. The computation of backedge masses is similar
/// but instead of having a single backedge mass, there will be one
/// backedge per loop header. In these cases, each backedge will carry
/// a mass proportional to the edge weights along the corresponding
/// path.
///
/// At the end of propagation, the full mass assigned to the loop will be
/// distributed among the loop headers proportionally according to the
/// mass flowing through their backedges.
///
/// Finally, calculate the loop scale from the accumulated backedge mass.
///
/// 3. Distribute mass in the function (\a computeMassInFunction()).
@ -735,11 +767,6 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
/// as sub-loops, rather than arbitrarily shoving the problematic
/// blocks into the headers of the main irreducible SCC.
///
/// - Backedge frequencies are assumed to be evenly split between the
/// headers of a given irreducible SCC. Instead, we could track the
/// backedge mass separately for each header, and adjust their relative
/// frequencies.
///
/// - Entry frequencies are assumed to be evenly split between the
/// headers of a given irreducible SCC, which is the only option if we
/// need to compute mass in the SCC before its parent loop. Instead,
@ -846,7 +873,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
///
/// \pre \a computeMassInLoop() has been called for each subloop of \c
/// OuterLoop.
/// \pre \c Insert points at the the last loop successfully processed by \a
/// \pre \c Insert points at the last loop successfully processed by \a
/// computeMassInLoop().
/// \pre \c OuterLoop has irreducible SCCs.
void computeIrreducibleMass(LoopData *OuterLoop,
@ -878,8 +905,8 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
public:
const FunctionT *getFunction() const { return F; }
void doFunction(const FunctionT *F, const BranchProbabilityInfoT *BPI,
const LoopInfoT *LI);
void calculate(const FunctionT &F, const BranchProbabilityInfoT &BPI,
const LoopInfoT &LI);
BlockFrequencyInfoImpl() : BPI(nullptr), LI(nullptr), F(nullptr) {}
using BlockFrequencyInfoImplBase::getEntryFreq;
@ -911,13 +938,13 @@ public:
};
template <class BT>
void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
const BranchProbabilityInfoT *BPI,
const LoopInfoT *LI) {
void BlockFrequencyInfoImpl<BT>::calculate(const FunctionT &F,
const BranchProbabilityInfoT &BPI,
const LoopInfoT &LI) {
// Save the parameters.
this->BPI = BPI;
this->LI = LI;
this->F = F;
this->BPI = &BPI;
this->LI = &LI;
this->F = &F;
// Clean up left-over data structures.
BlockFrequencyInfoImplBase::clear();
@ -925,8 +952,8 @@ void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
Nodes.clear();
// Initialize.
DEBUG(dbgs() << "\nblock-frequency: " << F->getName() << "\n================="
<< std::string(F->getName().size(), '=') << "\n");
DEBUG(dbgs() << "\nblock-frequency: " << F.getName() << "\n================="
<< std::string(F.getName().size(), '=') << "\n");
initializeRPOT();
initializeLoops();
@ -1042,6 +1069,8 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
for (const BlockNode &M : Loop.Nodes)
if (!propagateMassToSuccessors(&Loop, M))
llvm_unreachable("unhandled irreducible control flow");
adjustLoopHeaderMass(Loop);
} else {
Working[Loop.getHeader().Index].getMass() = BlockMass::getFull();
if (!propagateMassToSuccessors(&Loop, Loop.getHeader()))

View File

@ -25,9 +25,9 @@ namespace llvm {
class LoopInfo;
class raw_ostream;
/// \brief Analysis pass providing branch probability information.
/// \brief Analysis providing branch probability information.
///
/// This is a function analysis pass which provides information on the relative
/// This is a function analysis which provides information on the relative
/// probabilities of each "edge" in the function's CFG where such an edge is
/// defined by a pair (PredBlock and an index in the successors). The
/// probability of an edge from one block is always relative to the
@ -37,20 +37,14 @@ class raw_ostream;
/// identify an edge, since we can have multiple edges from Src to Dst.
/// As an example, we can have a switch which jumps to Dst with value 0 and
/// value 10.
class BranchProbabilityInfo : public FunctionPass {
class BranchProbabilityInfo {
public:
static char ID;
BranchProbabilityInfo() {}
BranchProbabilityInfo(Function &F, const LoopInfo &LI) { calculate(F, LI); }
BranchProbabilityInfo() : FunctionPass(ID) {
initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry());
}
void releaseMemory();
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M = nullptr) const override;
void print(raw_ostream &OS) const;
/// \brief Get an edge's probability, relative to other out-edges of the Src.
///
@ -118,6 +112,8 @@ public:
return IsLikely ? (1u << 20) - 1 : 1;
}
void calculate(Function &F, const LoopInfo& LI);
private:
// Since we allow duplicate edges from one basic block to another, we use
// a pair (PredBlock and an index in the successors) to specify an edge.
@ -133,9 +129,6 @@ private:
DenseMap<Edge, uint32_t> Weights;
/// \brief Handle to the LoopInfo analysis.
LoopInfo *LI;
/// \brief Track the last function we run over for printing.
Function *LastF;
@ -152,12 +145,33 @@ private:
bool calcMetadataWeights(BasicBlock *BB);
bool calcColdCallHeuristics(BasicBlock *BB);
bool calcPointerHeuristics(BasicBlock *BB);
bool calcLoopBranchHeuristics(BasicBlock *BB);
bool calcLoopBranchHeuristics(BasicBlock *BB, const LoopInfo &LI);
bool calcZeroHeuristics(BasicBlock *BB);
bool calcFloatingPointHeuristics(BasicBlock *BB);
bool calcInvokeHeuristics(BasicBlock *BB);
};
/// \brief Legacy analysis pass which computes \c BranchProbabilityInfo.
class BranchProbabilityInfoWrapperPass : public FunctionPass {
BranchProbabilityInfo BPI;
public:
static char ID;
BranchProbabilityInfoWrapperPass() : FunctionPass(ID) {
initializeBranchProbabilityInfoWrapperPassPass(
*PassRegistry::getPassRegistry());
}
BranchProbabilityInfo &getBPI() { return BPI; }
const BranchProbabilityInfo &getBPI() const { return BPI; }
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnFunction(Function &F) override;
void releaseMemory() override;
void print(raw_ostream &OS, const Module *M = nullptr) const override;
};
}
#endif

View File

@ -78,6 +78,17 @@ bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To,
const DominatorTree *DT = nullptr,
const LoopInfo *LI = nullptr);
/// \brief Determine whether there is at least one path from a block in
/// 'Worklist' to 'StopBB', returning true if uncertain.
///
/// Determine whether there is a path from at least one block in Worklist to
/// StopBB within a single function. Returns false only if we can prove that
/// once any block in 'Worklist' has been reached then 'StopBB' can not be
/// executed. Conservatively returns true.
bool isPotentiallyReachableFromMany(SmallVectorImpl<BasicBlock *> &Worklist,
BasicBlock *StopBB,
const DominatorTree *DT = nullptr,
const LoopInfo *LI = nullptr);
} // End llvm namespace
#endif

View File

@ -56,6 +56,7 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/ValueHandle.h"
#include "llvm/Pass.h"
#include <map>
@ -229,7 +230,8 @@ public:
/// \brief Adds a function to the list of functions called by this one.
void addCalledFunction(CallSite CS, CallGraphNode *M) {
assert(!CS.getInstruction() || !CS.getCalledFunction() ||
!CS.getCalledFunction()->isIntrinsic());
!CS.getCalledFunction()->isIntrinsic() ||
!Intrinsic::isLeaf(CS.getCalledFunction()->getIntrinsicID()));
CalledFunctions.emplace_back(CS.getInstruction(), M);
M->AddRef();
}

View File

@ -20,6 +20,7 @@ namespace llvm {
class Use;
class Instruction;
class DominatorTree;
class OrderedBasicBlock;
/// PointerMayBeCaptured - Return true if this pointer value may be captured
/// by the enclosing function (which is required to exist). This routine can
@ -41,10 +42,12 @@ namespace llvm {
/// it or not. The boolean StoreCaptures specified whether storing the value
/// (or part of it) into memory anywhere automatically counts as capturing it
/// or not. Captures by the provided instruction are considered if the
/// final parameter is true.
/// final parameter is true. An ordered basic block in \p OBB could be used
/// to speed up capture-tracker queries.
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
bool StoreCaptures, const Instruction *I,
DominatorTree *DT, bool IncludeI = false);
DominatorTree *DT, bool IncludeI = false,
OrderedBasicBlock *OBB = nullptr);
/// This callback is used in conjunction with PointerMayBeCaptured. In
/// addition to the interface here, you'll need to provide your own getters

View File

@ -72,6 +72,17 @@ namespace llvm {
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
ArrayRef<unsigned> Idxs);
/// \brief Attempt to constant fold an extractvalue instruction with the
/// specified operands and indices. The constant result is returned if
/// successful; if not, null is returned.
Constant *ConstantFoldExtractValueInstruction(Constant *Agg,
ArrayRef<unsigned> Idxs);
/// \brief Attempt to constant fold an extractelement instruction with the
/// specified operands and indices. The constant result is returned if
/// successful; if not, null is returned.
Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx);
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
/// produce if it is constant and determinable. If this is not determinable,
/// return null.

View File

@ -202,8 +202,8 @@ public:
void dump() const;
};
EXTERN_TEMPLATE_INSTANTIATION(class DominanceFrontierBase<BasicBlock>);
EXTERN_TEMPLATE_INSTANTIATION(class ForwardDominanceFrontierBase<BasicBlock>);
extern template class DominanceFrontierBase<BasicBlock>;
extern template class ForwardDominanceFrontierBase<BasicBlock>;
} // End llvm namespace

View File

@ -21,6 +21,7 @@
namespace llvm {
class AssumptionCache;
class DominatorTree;
class Instruction;
class Value;
@ -119,15 +120,19 @@ private:
class IVUsers : public LoopPass {
friend class IVStrideUse;
Loop *L;
AssumptionCache *AC;
LoopInfo *LI;
DominatorTree *DT;
ScalarEvolution *SE;
SmallPtrSet<Instruction*,16> Processed;
SmallPtrSet<Instruction*, 16> Processed;
/// IVUses - A list of all tracked IV uses of induction variable expressions
/// we are interested in.
ilist<IVStrideUse> IVUses;
// Ephemeral values used by @llvm.assume in this function.
SmallPtrSet<const Value *, 32> EphValues;
void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnLoop(Loop *L, LPPassManager &LPM) override;

View File

@ -212,7 +212,7 @@ namespace llvm {
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result. If not, this returns null.
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout &DL,
FastMathFlags FMF, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
@ -244,6 +244,24 @@ namespace llvm {
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// \brief Given operands for an ExtractValueInst, see if we can fold the
/// result. If not, this returns null.
Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// \brief Given operands for an ExtractElementInst, see if we can fold the
/// result. If not, this returns null.
Value *SimplifyExtractElementInst(Value *Vec, Value *Idx,
const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr,
const Instruction *CxtI = nullptr);
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
/// the result. If not, this returns null.
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL,

View File

@ -1,71 +0,0 @@
//===-- JumpInstrTableInfo.h: Info for Jump-Instruction Tables --*- C++ -*-===//
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// \brief Information about jump-instruction tables that have been created by
/// JumpInstrTables pass.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H
#define LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/Pass.h"
#include <vector>
namespace llvm {
class Function;
class FunctionType;
/// This class stores information about jump-instruction tables created by the
/// JumpInstrTables pass (in lib/CodeGen/JumpInstrTables.cpp). Each table is a
/// map from a function type to a vector of pairs. The first element of each
/// pair is the function that has the jumptable annotation. The second element
/// is a function that was declared by JumpInstrTables and used to replace all
/// address-taking sites for the original function.
///
/// The information in this pass is used in AsmPrinter
/// (lib/CodeGen/AsmPrinter/AsmPrinter.cpp) to generate the required assembly
/// for the jump-instruction tables.
class JumpInstrTableInfo : public ImmutablePass {
public:
static char ID;
/// The default byte alignment for jump tables is 16, which is large but
/// usually safe.
JumpInstrTableInfo(uint64_t ByteAlign = 16);
~JumpInstrTableInfo() override;
const char *getPassName() const override {
return "Jump-Instruction Table Info";
}
typedef std::pair<Function *, Function *> JumpPair;
typedef DenseMap<FunctionType *, std::vector<JumpPair> > JumpTables;
/// Inserts an entry in a table, adding the table if it doesn't exist.
void insertEntry(FunctionType *TableFunTy, Function *Target, Function *Jump);
/// Gets the tables.
const JumpTables &getTables() const { return Tables; }
/// Gets the alignment in bytes of a jumptable entry.
uint64_t entryByteAlignment() const { return ByteAlignment; }
private:
JumpTables Tables;
/// A power-of-two alignment of a jumptable entry.
uint64_t ByteAlignment;
};
/// Creates a JumpInstrTableInfo pass with the given bound on entry size. This
/// bound specifies the maximum number of bytes needed to represent an
/// unconditional jump or a trap instruction in the back end currently in use.
ModulePass *createJumpInstrTableInfoPass(unsigned Bound);
}
#endif /* LLVM_ANALYSIS_JUMPINSTRTABLEINFO_H */

View File

@ -190,7 +190,7 @@ public:
Function &getFunction() const {
return F;
};
}
iterator begin() const {
return iterator(*G, Callees.begin(), Callees.end());

View File

@ -25,7 +25,7 @@ namespace llvm {
class Instruction;
class TargetLibraryInfo;
class Value;
/// This pass computes, caches, and vends lazy value constraint information.
class LazyValueInfo : public FunctionPass {
AssumptionCache *AC;
@ -45,23 +45,22 @@ public:
enum Tristate {
Unknown = -1, False = 0, True = 1
};
// Public query interface.
/// Determine whether the specified value comparison with a constant is known
/// to be true or false on the specified CFG edge.
/// Pred is a CmpInst predicate.
Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
BasicBlock *FromBB, BasicBlock *ToBB,
Instruction *CxtI = nullptr);
/// Determine whether the specified value comparison with a constant is known
/// to be true or false at the specified instruction
/// (from an assume intrinsic). Pred is a CmpInst predicate.
Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C,
Instruction *CxtI);
/// Determine whether the specified value is known to be a
/// constant at the end of the specified block. Return null if not.
Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr);
@ -70,14 +69,14 @@ public:
/// constant on the specified edge. Return null if not.
Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
Instruction *CxtI = nullptr);
/// Inform the analysis cache that we have threaded an edge from
/// PredBB to OldSucc to be from PredBB to NewSucc instead.
void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);
/// Inform the analysis cache that we have erased a block.
void eraseBlock(BasicBlock *BB);
// Implementation boilerplate.
void getAnalysisUsage(AnalysisUsage &AU) const override;

View File

@ -38,11 +38,11 @@ namespace llvm {
}
~LibCallAliasAnalysis() override;
ModRefResult getModRefInfo(ImmutableCallSite CS,
const Location &Loc) override;
ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) override {
ModRefInfo getModRefInfo(ImmutableCallSite CS,
const MemoryLocation &Loc) override;
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2) override {
// TODO: Could compare two direct calls against each other if we cared to.
return AliasAnalysis::getModRefInfo(CS1, CS2);
}
@ -62,9 +62,9 @@ namespace llvm {
}
private:
ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
ImmutableCallSite CS,
const Location &Loc);
ModRefInfo AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
ImmutableCallSite CS,
const MemoryLocation &Loc);
};
} // End of llvm namespace

View File

@ -48,8 +48,7 @@ class InvokeInst;
enum LocResult {
Yes, No, Unknown
};
LocResult (*isLocation)(ImmutableCallSite CS,
const AliasAnalysis::Location &Loc);
LocResult (*isLocation)(ImmutableCallSite CS, const MemoryLocation &Loc);
};
/// LibCallFunctionInfo - Each record in the array of FunctionInfo structs
@ -72,15 +71,15 @@ class InvokeInst;
/// any specific context knowledge. For example, if the function is known
/// to be readonly, this would be set to 'ref'. If known to be readnone,
/// this is set to NoModRef.
AliasAnalysis::ModRefResult UniversalBehavior;
ModRefInfo UniversalBehavior;
/// LocationMRInfo - This pair captures info about whether a specific
/// location is modified or referenced by a libcall.
struct LocationMRInfo {
/// LocationID - ID # of the accessed location or ~0U for array end.
unsigned LocationID;
/// MRInfo - Mod/Ref info for this location.
AliasAnalysis::ModRefResult MRInfo;
ModRefInfo MRInfo;
};
/// DetailsType - Indicate the sense of the LocationDetails array. This
@ -207,7 +206,19 @@ class InvokeInst;
llvm_unreachable("invalid enum");
}
bool canSimplifyInvokeNoUnwind(const InvokeInst *II);
/// \brief Return true if this personality may be safely removed if there
/// are no invoke instructions remaining in the current function.
inline bool isNoOpWithoutInvoke(EHPersonality Pers) {
switch (Pers) {
case EHPersonality::Unknown:
return false;
// All known personalities currently have this behavior
default: return true;
}
llvm_unreachable("invalid enum");
}
bool canSimplifyInvokeNoUnwind(const Function *F);
} // end namespace llvm

View File

@ -292,6 +292,163 @@ private:
bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize);
};
/// \brief Holds information about the memory runtime legality checks to verify
/// that a group of pointers do not overlap.
class RuntimePointerChecking {
public:
struct PointerInfo {
/// Holds the pointer value that we need to check.
TrackingVH<Value> PointerValue;
/// Holds the pointer value at the beginning of the loop.
const SCEV *Start;
/// Holds the pointer value at the end of the loop.
const SCEV *End;
/// Holds the information if this pointer is used for writing to memory.
bool IsWritePtr;
/// Holds the id of the set of pointers that could be dependent because of a
/// shared underlying object.
unsigned DependencySetId;
/// Holds the id of the disjoint alias set to which this pointer belongs.
unsigned AliasSetId;
/// SCEV for the access.
const SCEV *Expr;
PointerInfo(Value *PointerValue, const SCEV *Start, const SCEV *End,
bool IsWritePtr, unsigned DependencySetId, unsigned AliasSetId,
const SCEV *Expr)
: PointerValue(PointerValue), Start(Start), End(End),
IsWritePtr(IsWritePtr), DependencySetId(DependencySetId),
AliasSetId(AliasSetId), Expr(Expr) {}
};
RuntimePointerChecking(ScalarEvolution *SE) : Need(false), SE(SE) {}
/// Reset the state of the pointer runtime information.
void reset() {
Need = false;
Pointers.clear();
}
/// Insert a pointer and calculate the start and end SCEVs.
void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,
unsigned ASId, const ValueToValueMap &Strides);
/// \brief No run-time memory checking is necessary.
bool empty() const { return Pointers.empty(); }
/// A grouping of pointers. A single memcheck is required between
/// two groups.
struct CheckingPtrGroup {
/// \brief Create a new pointer checking group containing a single
/// pointer, with index \p Index in RtCheck.
CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck)
: RtCheck(RtCheck), High(RtCheck.Pointers[Index].End),
Low(RtCheck.Pointers[Index].Start) {
Members.push_back(Index);
}
/// \brief Tries to add the pointer recorded in RtCheck at index
/// \p Index to this pointer checking group. We can only add a pointer
/// to a checking group if we will still be able to get
/// the upper and lower bounds of the check. Returns true in case
/// of success, false otherwise.
bool addPointer(unsigned Index);
/// Constitutes the context of this pointer checking group. For each
/// pointer that is a member of this group we will retain the index
/// at which it appears in RtCheck.
RuntimePointerChecking &RtCheck;
/// The SCEV expression which represents the upper bound of all the
/// pointers in this group.
const SCEV *High;
/// The SCEV expression which represents the lower bound of all the
/// pointers in this group.
const SCEV *Low;
/// Indices of all the pointers that constitute this grouping.
SmallVector<unsigned, 2> Members;
};
/// \brief A memcheck which made up of a pair of grouped pointers.
///
/// These *have* to be const for now, since checks are generated from
/// CheckingPtrGroups in LAI::addRuntimeCheck which is a const member
/// function. FIXME: once check-generation is moved inside this class (after
/// the PtrPartition hack is removed), we could drop const.
typedef std::pair<const CheckingPtrGroup *, const CheckingPtrGroup *>
PointerCheck;
/// \brief Groups pointers such that a single memcheck is required
/// between two different groups. This will clear the CheckingGroups vector
/// and re-compute it. We will only group dependecies if \p UseDependencies
/// is true, otherwise we will create a separate group for each pointer.
void groupChecks(MemoryDepChecker::DepCandidates &DepCands,
bool UseDependencies);
/// Generate the checks and return them.
///
/// \p PtrToPartition contains the partition number for pointers. If passed,
/// omit checks between pointers belonging to the same partition. Partition
/// number -1 means that the pointer is used in multiple partitions. In this
/// case we can't safely omit the check.
SmallVector<PointerCheck, 4>
generateChecks(const SmallVectorImpl<int> *PtrPartition = nullptr) const;
/// \brief Decide if we need to add a check between two groups of pointers,
/// according to needsChecking.
bool needsChecking(const CheckingPtrGroup &M, const CheckingPtrGroup &N,
const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Return true if any pointer requires run-time checking according
/// to needsChecking.
bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Returns the number of run-time checks required according to
/// needsChecking.
unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Print the list run-time memory checks necessary.
///
/// If \p PtrPartition is set, it contains the partition number for
/// pointers (-1 if the pointer belongs to multiple partitions). In this
/// case omit checks between pointers belonging to the same partition.
void print(raw_ostream &OS, unsigned Depth = 0,
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
/// Print \p Checks.
void printChecks(raw_ostream &OS, const SmallVectorImpl<PointerCheck> &Checks,
unsigned Depth = 0) const;
/// This flag indicates if we need to add the runtime check.
bool Need;
/// Information about the pointers that may require checking.
SmallVector<PointerInfo, 2> Pointers;
/// Holds a partitioning of pointers into "check groups".
SmallVector<CheckingPtrGroup, 2> CheckingGroups;
/// \brief Check if pointers are in the same partition
///
/// \p PtrToPartition contains the partition number for pointers (-1 if the
/// pointer belongs to multiple partitions).
static bool
arePointersInSamePartition(const SmallVectorImpl<int> &PtrToPartition,
unsigned PtrIdx1, unsigned PtrIdx2);
/// \brief Decide whether we need to issue a run-time check for pointer at
/// index \p I and \p J to prove their independence.
///
/// If \p PtrPartition is set, it contains the partition number for
/// pointers (-1 if the pointer belongs to multiple partitions). In this
/// case omit checks between pointers belonging to the same partition.
bool needsChecking(unsigned I, unsigned J,
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
private:
/// Holds a pointer to the ScalarEvolution analysis.
ScalarEvolution *SE;
};
/// \brief Drive the analysis of memory accesses in the loop
///
/// This class is responsible for analyzing the memory accesses of a loop. It
@ -308,72 +465,6 @@ private:
/// RuntimePointerCheck class.
class LoopAccessInfo {
public:
/// This struct holds information about the memory runtime legality check that
/// a group of pointers do not overlap.
struct RuntimePointerCheck {
RuntimePointerCheck() : Need(false) {}
/// Reset the state of the pointer runtime information.
void reset() {
Need = false;
Pointers.clear();
Starts.clear();
Ends.clear();
IsWritePtr.clear();
DependencySetId.clear();
AliasSetId.clear();
}
/// Insert a pointer and calculate the start and end SCEVs.
void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr,
unsigned DepSetId, unsigned ASId,
const ValueToValueMap &Strides);
/// \brief No run-time memory checking is necessary.
bool empty() const { return Pointers.empty(); }
/// \brief Decide whether we need to issue a run-time check for pointer at
/// index \p I and \p J to prove their independence.
///
/// If \p PtrPartition is set, it contains the partition number for
/// pointers (-1 if the pointer belongs to multiple partitions). In this
/// case omit checks between pointers belonging to the same partition.
bool needsChecking(unsigned I, unsigned J,
const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Return true if any pointer requires run-time checking according
/// to needsChecking.
bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Returns the number of run-time checks required according to
/// needsChecking.
unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Print the list run-time memory checks necessary.
///
/// If \p PtrPartition is set, it contains the partition number for
/// pointers (-1 if the pointer belongs to multiple partitions). In this
/// case omit checks between pointers belonging to the same partition.
void print(raw_ostream &OS, unsigned Depth = 0,
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
/// This flag indicates if we need to add the runtime check.
bool Need;
/// Holds the pointers that we need to check.
SmallVector<TrackingVH<Value>, 2> Pointers;
/// Holds the pointer value at the beginning of the loop.
SmallVector<const SCEV*, 2> Starts;
/// Holds the pointer value at the end of the loop.
SmallVector<const SCEV*, 2> Ends;
/// Holds the information if this pointer is used for writing to memory.
SmallVector<bool, 2> IsWritePtr;
/// Holds the id of the set of pointers that could be dependent because of a
/// shared underlying object.
SmallVector<unsigned, 2> DependencySetId;
/// Holds the id of the disjoint alias set to which this pointer belongs.
SmallVector<unsigned, 2> AliasSetId;
};
LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,
const TargetLibraryInfo *TLI, AliasAnalysis *AA,
DominatorTree *DT, LoopInfo *LI,
@ -383,15 +474,15 @@ public:
/// no memory dependence cycles.
bool canVectorizeMemory() const { return CanVecMem; }
const RuntimePointerCheck *getRuntimePointerCheck() const {
return &PtrRtCheck;
const RuntimePointerChecking *getRuntimePointerChecking() const {
return &PtrRtChecking;
}
/// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers.
unsigned getNumRuntimePointerChecks(
const SmallVectorImpl<int> *PtrPartition = nullptr) const {
return PtrRtCheck.getNumberOfChecks(PtrPartition);
return PtrRtChecking.getNumberOfChecks(PtrPartition);
}
/// Return true if the block BB needs to be predicated in order for the loop
@ -419,6 +510,16 @@ public:
addRuntimeCheck(Instruction *Loc,
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
/// \brief Generete the instructions for the checks in \p PointerChecks.
///
/// Returns a pair of instructions where the first element is the first
/// instruction generated in possibly a sequence of instructions and the
/// second value is the final comparator value or NULL if no check is needed.
std::pair<Instruction *, Instruction *>
addRuntimeCheck(Instruction *Loc,
const SmallVectorImpl<RuntimePointerChecking::PointerCheck>
&PointerChecks) const;
/// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop.
const Optional<LoopAccessReport> &getReport() const { return Report; }
@ -461,7 +562,7 @@ private:
/// We need to check that all of the pointers in this list are disjoint
/// at runtime.
RuntimePointerCheck PtrRtCheck;
RuntimePointerChecking PtrRtChecking;
/// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses.

View File

@ -347,9 +347,7 @@ raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) {
}
// Implementation in LoopInfoImpl.h
#ifdef __GNUC__
__extension__ extern template class LoopBase<BasicBlock, Loop>;
#endif
extern template class LoopBase<BasicBlock, Loop>;
class Loop : public LoopBase<BasicBlock, Loop> {
public:
@ -624,7 +622,7 @@ public:
}
/// Create the loop forest using a stable algorithm.
void Analyze(DominatorTreeBase<BlockT> &DomTree);
void analyze(const DominatorTreeBase<BlockT> &DomTree);
// Debugging
void print(raw_ostream &OS) const;
@ -633,9 +631,7 @@ public:
};
// Implementation in LoopInfoImpl.h
#ifdef __GNUC__
__extension__ extern template class LoopInfoBase<BasicBlock, Loop>;
#endif
extern template class LoopInfoBase<BasicBlock, Loop>;
class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
typedef LoopInfoBase<BasicBlock, Loop> BaseT;
@ -646,6 +642,7 @@ class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
LoopInfo(const LoopInfo &) = delete;
public:
LoopInfo() {}
explicit LoopInfo(const DominatorTreeBase<BasicBlock> &DomTree);
LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
LoopInfo &operator=(LoopInfo &&RHS) {

View File

@ -345,7 +345,7 @@ void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth) const {
template<class BlockT, class LoopT>
static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
LoopInfoBase<BlockT, LoopT> *LI,
DominatorTreeBase<BlockT> &DomTree) {
const DominatorTreeBase<BlockT> &DomTree) {
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
unsigned NumBlocks = 0;
@ -468,10 +468,10 @@ void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) {
/// insertions per block.
template<class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>::
Analyze(DominatorTreeBase<BlockT> &DomTree) {
analyze(const DominatorTreeBase<BlockT> &DomTree) {
// Postorder traversal of the dominator tree.
DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode();
const DomTreeNodeBase<BlockT> *DomRoot = DomTree.getRootNode();
for (auto DomNode : post_order(DomRoot)) {
BlockT *Header = DomNode->getBlock();

View File

@ -287,7 +287,7 @@ namespace llvm {
/// conflicting tags.
AAMDNodes AATags;
NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize) {}
NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {}
};
/// CachedNonLocalPointerInfo - This map stores the cached results of doing
@ -403,13 +403,12 @@ namespace llvm {
///
/// Note that this is an uncached query, and thus may be inefficient.
///
MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc,
MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc,
bool isLoad,
BasicBlock::iterator ScanIt,
BasicBlock *BB,
Instruction *QueryInst = nullptr);
/// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that
/// looks at a memory location for a load (specified by MemLocBase, Offs,
/// and Size) and compares it against a load. If the specified load could
@ -428,15 +427,14 @@ namespace llvm {
BasicBlock *BB);
bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
const PHITransAddr &Pointer,
const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
const MemoryLocation &Loc, bool isLoad,
BasicBlock *BB,
SmallVectorImpl<NonLocalDepResult> &Result,
DenseMap<BasicBlock*, Value*> &Visited,
DenseMap<BasicBlock *, Value *> &Visited,
bool SkipFirstBlock = false);
MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst,
const AliasAnalysis::Location &Loc,
bool isLoad, BasicBlock *BB,
NonLocalDepInfo *Cache,
const MemoryLocation &Loc, bool isLoad,
BasicBlock *BB, NonLocalDepInfo *Cache,
unsigned NumSortedEntries);
void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P);

View File

@ -26,6 +26,7 @@ class LoadInst;
class StoreInst;
class MemTransferInst;
class MemIntrinsic;
class TargetLibraryInfo;
/// Representation for a specific memory location.
///
@ -87,6 +88,10 @@ public:
/// transfer.
static MemoryLocation getForDest(const MemIntrinsic *MI);
/// Return a location representing a particular argument of a call.
static MemoryLocation getForArgument(ImmutableCallSite CS, unsigned ArgIdx,
const TargetLibraryInfo &TLI);
explicit MemoryLocation(const Value *Ptr = nullptr,
uint64_t Size = UnknownSize,
const AAMDNodes &AATags = AAMDNodes())

View File

@ -0,0 +1,66 @@
//===- llvm/Analysis/OrderedBasicBlock.h --------------------- -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the OrderedBasicBlock class. OrderedBasicBlock maintains
// an interface where clients can query if one instruction comes before another
// in a BasicBlock. Since BasicBlock currently lacks a reliable way to query
// relative position between instructions one can use OrderedBasicBlock to do
// such queries. OrderedBasicBlock is lazily built on a source BasicBlock and
// maintains an internal Instruction -> Position map. A OrderedBasicBlock
// instance should be discarded whenever the source BasicBlock changes.
//
// It's currently used by the CaptureTracker in order to find relative
// positions of a pair of instructions inside a BasicBlock.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_ORDEREDBASICBLOCK_H
#define LLVM_ANALYSIS_ORDEREDBASICBLOCK_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/BasicBlock.h"
namespace llvm {
class Instruction;
class BasicBlock;
class OrderedBasicBlock {
private:
/// \brief Map a instruction to its position in a BasicBlock.
SmallDenseMap<const Instruction *, unsigned, 32> NumberedInsts;
/// \brief Keep track of last instruction inserted into \p NumberedInsts.
/// It speeds up queries for uncached instructions by providing a start point
/// for new queries in OrderedBasicBlock::comesBefore.
BasicBlock::const_iterator LastInstFound;
/// \brief The position/number to tag the next instruction to be found.
unsigned NextInstPos;
/// \brief The source BasicBlock to map.
const BasicBlock *BB;
/// \brief Given no cached results, find if \p A comes before \p B in \p BB.
/// Cache and number out instruction while walking \p BB.
bool comesBefore(const Instruction *A, const Instruction *B);
public:
OrderedBasicBlock(const BasicBlock *BasicB);
/// \brief Find out whether \p A dominates \p B, meaning whether \p A
/// comes before \p B in \p BB. This is a simplification that considers
/// cached instruction positions and ignores other basic blocks, being
/// only relevant to compare relative instructions positions inside \p BB.
bool dominates(const Instruction *A, const Instruction *B);
};
} // End llvm namespace
#endif

View File

@ -902,9 +902,9 @@ inline raw_ostream &operator<<(raw_ostream &OS,
return OS << Node.template getNodeAs<BlockT>()->getName();
}
EXTERN_TEMPLATE_INSTANTIATION(class RegionBase<RegionTraits<Function>>);
EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase<RegionTraits<Function>>);
EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase<RegionTraits<Function>>);
extern template class RegionBase<RegionTraits<Function>>;
extern template class RegionNodeBase<RegionTraits<Function>>;
extern template class RegionInfoBase<RegionTraits<Function>>;
} // End llvm namespace
#endif

View File

@ -48,6 +48,7 @@ namespace llvm {
class LoopInfo;
class Operator;
class SCEVUnknown;
class SCEVAddRecExpr;
class SCEV;
template<> struct FoldingSetTrait<SCEV>;
@ -565,19 +566,43 @@ namespace llvm {
/// forgetMemoizedResults - Drop memoized information computed for S.
void forgetMemoizedResults(const SCEV *S);
/// Return an existing SCEV for V if there is one, otherwise return nullptr.
const SCEV *getExistingSCEV(Value *V);
/// Return false iff given SCEV contains a SCEVUnknown with NULL value-
/// pointer.
bool checkValidity(const SCEV *S) const;
// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be equal
// to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is equivalent to
// proving no signed (resp. unsigned) wrap in {`Start`,+,`Step`} if
// `ExtendOpTy` is `SCEVSignExtendExpr` (resp. `SCEVZeroExtendExpr`).
//
/// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be
/// equal to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is
/// equivalent to proving no signed (resp. unsigned) wrap in
/// {`Start`,+,`Step`} if `ExtendOpTy` is `SCEVSignExtendExpr`
/// (resp. `SCEVZeroExtendExpr`).
///
template<typename ExtendOpTy>
bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
const Loop *L);
bool isMonotonicPredicateImpl(const SCEVAddRecExpr *LHS,
ICmpInst::Predicate Pred, bool &Increasing);
/// Return true if, for all loop invariant X, the predicate "LHS `Pred` X"
/// is monotonically increasing or decreasing. In the former case set
/// `Increasing` to true and in the latter case set `Increasing` to false.
///
/// A predicate is said to be monotonically increasing if may go from being
/// false to being true as the loop iterates, but never the other way
/// around. A predicate is said to be monotonically decreasing if may go
/// from being true to being false as the loop iterates, but never the other
/// way around.
bool isMonotonicPredicate(const SCEVAddRecExpr *LHS,
ICmpInst::Predicate Pred, bool &Increasing);
// Return SCEV no-wrap flags that can be proven based on reasoning
// about how poison produced from no-wrap flags on this value
// (e.g. a nuw add) would trigger undefined behavior on overflow.
SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V);
public:
static char ID; // Pass identification, replacement for typeid
ScalarEvolution();
@ -899,6 +924,16 @@ namespace llvm {
bool isKnownPredicate(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS);
/// Return true if the result of the predicate LHS `Pred` RHS is loop
/// invariant with respect to L. Set InvariantPred, InvariantLHS and
/// InvariantLHS so that InvariantLHS `InvariantPred` InvariantRHS is the
/// loop invariant form of LHS `Pred` RHS.
bool isLoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS,
const SCEV *RHS, const Loop *L,
ICmpInst::Predicate &InvariantPred,
const SCEV *&InvariantLHS,
const SCEV *&InvariantRHS);
/// SimplifyICmpOperands - Simplify LHS and RHS in a comparison with
/// predicate Pred. Return true iff any changes were made. If the
/// operands are provably equal or unequal, LHS and RHS are set to
@ -954,6 +989,86 @@ namespace llvm {
void print(raw_ostream &OS, const Module* = nullptr) const override;
void verifyAnalysis() const override;
/// Collect parametric terms occurring in step expressions.
void collectParametricTerms(const SCEV *Expr,
SmallVectorImpl<const SCEV *> &Terms);
/// Return in Subscripts the access functions for each dimension in Sizes.
void computeAccessFunctions(const SCEV *Expr,
SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<const SCEV *> &Sizes);
/// Split this SCEVAddRecExpr into two vectors of SCEVs representing the
/// subscripts and sizes of an array access.
///
/// The delinearization is a 3 step process: the first two steps compute the
/// sizes of each subscript and the third step computes the access functions
/// for the delinearized array:
///
/// 1. Find the terms in the step functions
/// 2. Compute the array size
/// 3. Compute the access function: divide the SCEV by the array size
/// starting with the innermost dimensions found in step 2. The Quotient
/// is the SCEV to be divided in the next step of the recursion. The
/// Remainder is the subscript of the innermost dimension. Loop over all
/// array dimensions computed in step 2.
///
/// To compute a uniform array size for several memory accesses to the same
/// object, one can collect in step 1 all the step terms for all the memory
/// accesses, and compute in step 2 a unique array shape. This guarantees
/// that the array shape will be the same across all memory accesses.
///
/// FIXME: We could derive the result of steps 1 and 2 from a description of
/// the array shape given in metadata.
///
/// Example:
///
/// A[][n][m]
///
/// for i
/// for j
/// for k
/// A[j+k][2i][5i] =
///
/// The initial SCEV:
///
/// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k]
///
/// 1. Find the different terms in the step functions:
/// -> [2*m, 5, n*m, n*m]
///
/// 2. Compute the array size: sort and unique them
/// -> [n*m, 2*m, 5]
/// find the GCD of all the terms = 1
/// divide by the GCD and erase constant terms
/// -> [n*m, 2*m]
/// GCD = m
/// divide by GCD -> [n, 2]
/// remove constant terms
/// -> [n]
/// size of the array is A[unknown][n][m]
///
/// 3. Compute the access function
/// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m
/// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k
/// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k
/// The remainder is the subscript of the innermost array dimension: [5i].
///
/// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n
/// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k
/// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k
/// The Remainder is the subscript of the next array dimension: [2i].
///
/// The subscript of the outermost dimension is the Quotient: [j+k].
///
/// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i].
void delinearize(const SCEV *Expr,
SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<const SCEV *> &Sizes,
const SCEV *ElementSize);
private:
/// Compute the backedge taken count knowing the interval difference, the
/// stride and presence of the equality in the comparison.

View File

@ -356,84 +356,6 @@ namespace llvm {
static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scAddRecExpr;
}
/// Collect parametric terms occurring in step expressions.
void collectParametricTerms(ScalarEvolution &SE,
SmallVectorImpl<const SCEV *> &Terms) const;
/// Return in Subscripts the access functions for each dimension in Sizes.
void computeAccessFunctions(ScalarEvolution &SE,
SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<const SCEV *> &Sizes) const;
/// Split this SCEVAddRecExpr into two vectors of SCEVs representing the
/// subscripts and sizes of an array access.
///
/// The delinearization is a 3 step process: the first two steps compute the
/// sizes of each subscript and the third step computes the access functions
/// for the delinearized array:
///
/// 1. Find the terms in the step functions
/// 2. Compute the array size
/// 3. Compute the access function: divide the SCEV by the array size
/// starting with the innermost dimensions found in step 2. The Quotient
/// is the SCEV to be divided in the next step of the recursion. The
/// Remainder is the subscript of the innermost dimension. Loop over all
/// array dimensions computed in step 2.
///
/// To compute a uniform array size for several memory accesses to the same
/// object, one can collect in step 1 all the step terms for all the memory
/// accesses, and compute in step 2 a unique array shape. This guarantees
/// that the array shape will be the same across all memory accesses.
///
/// FIXME: We could derive the result of steps 1 and 2 from a description of
/// the array shape given in metadata.
///
/// Example:
///
/// A[][n][m]
///
/// for i
/// for j
/// for k
/// A[j+k][2i][5i] =
///
/// The initial SCEV:
///
/// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k]
///
/// 1. Find the different terms in the step functions:
/// -> [2*m, 5, n*m, n*m]
///
/// 2. Compute the array size: sort and unique them
/// -> [n*m, 2*m, 5]
/// find the GCD of all the terms = 1
/// divide by the GCD and erase constant terms
/// -> [n*m, 2*m]
/// GCD = m
/// divide by GCD -> [n, 2]
/// remove constant terms
/// -> [n]
/// size of the array is A[unknown][n][m]
///
/// 3. Compute the access function
/// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m
/// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k
/// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k
/// The remainder is the subscript of the innermost array dimension: [5i].
///
/// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n
/// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k
/// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k
/// The Remainder is the subscript of the next array dimension: [2i].
///
/// The subscript of the outermost dimension is the Quotient: [j+k].
///
/// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i].
void delinearize(ScalarEvolution &SE,
SmallVectorImpl<const SCEV *> &Subscripts,
SmallVectorImpl<const SCEV *> &Sizes,
const SCEV *ElementSize) const;
};
//===--------------------------------------------------------------------===//

Some files were not shown because too many files have changed in this diff Show More