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. # External projects that are tracked independently.
projects/* projects/*
!projects/CMakeLists.txt !projects/*.*
!projects/Makefile !projects/Makefile
# Clang, which is tracked independently. # Clang, which is tracked independently.
tools/clang tools/clang

View File

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

View File

@ -65,6 +65,10 @@ N: Hal Finkel
E: hfinkel@anl.gov E: hfinkel@anl.gov
D: BBVectorize, the loop reroller, alias analysis and the PowerPC target 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 N: Renato Golin
E: renato.golin@linaro.org E: renato.golin@linaro.org
D: ARM Linux support D: ARM Linux support

View File

@ -152,8 +152,9 @@ E: foldr@codedgers.com
D: Author of llvmc2 D: Author of llvmc2
N: Dan Gohman N: Dan Gohman
E: dan433584@gmail.com E: sunfish@mozilla.com
D: Miscellaneous bug fixes D: Miscellaneous bug fixes
D: WebAssembly Backend
N: David Goodwin N: David Goodwin
E: david@goodwinz.net 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_ROOT := $(LLVM_SRC_ROOT)
PROJ_SRC_DIR := $(LLVM_SRC_ROOT)$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR)) 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 # See: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150323/268067.html
ifeq ($(LLVM_SRC_ROOT), $(LLVM_OBJ_ROOT)) ifeq ($(LLVM_SRC_ROOT), $(LLVM_OBJ_ROOT))
$(warning ######################################################################################) $(error In-source builds are not allowed. Please configure from a separate build directory!)
$(warning # #)
$(warning # WARNING #)
$(warning # #)
$(warning # In-source builds are deprecated. #)
$(warning # #)
$(warning # Please configure from a separate build directory! #)
$(warning # #)
$(warning ######################################################################################)
endif endif
ifneq ($(CLANG_SRC_ROOT),) ifneq ($(CLANG_SRC_ROOT),)

View File

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

View File

@ -32,10 +32,10 @@ dnl===-----------------------------------------------------------------------===
dnl Initialize autoconf and define the package name, version number and dnl Initialize autoconf and define the package name, version number and
dnl address for reporting bugs. 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_MAJOR=3
LLVM_VERSION_MINOR=7 LLVM_VERSION_MINOR=8
LLVM_VERSION_PATCH=0 LLVM_VERSION_PATCH=0
LLVM_VERSION_SUFFIX=svn LLVM_VERSION_SUFFIX=svn
@ -75,15 +75,7 @@ fi
dnl Quit if it is an in-source build dnl Quit if it is an in-source build
if test ${srcdir} == "." ; then if test ${srcdir} == "." ; then
AC_MSG_WARN([**************************************************************************************]) AC_MSG_ERROR([In-source builds are not allowed. Please configure from a separate build directory!])
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([**************************************************************************************])
fi fi
dnl Default to empty (i.e. assigning the null string to) CFLAGS and CXXFLAGS, 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" ;; hexagon-*) llvm_cv_target_arch="Hexagon" ;;
nvptx-*) llvm_cv_target_arch="NVPTX" ;; nvptx-*) llvm_cv_target_arch="NVPTX" ;;
s390x-*) llvm_cv_target_arch="SystemZ" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;;
wasm*-*) llvm_cv_target_arch="WebAssembly" ;;
*) llvm_cv_target_arch="Unknown" ;; *) llvm_cv_target_arch="Unknown" ;;
esac]) esac])
@ -480,6 +473,7 @@ case $host in
msp430-*) host_arch="MSP430" ;; msp430-*) host_arch="MSP430" ;;
hexagon-*) host_arch="Hexagon" ;; hexagon-*) host_arch="Hexagon" ;;
s390x-*) host_arch="SystemZ" ;; s390x-*) host_arch="SystemZ" ;;
wasm*-*) host_arch="WebAssembly" ;;
*) host_arch="Unknown" ;; *) host_arch="Unknown" ;;
esac esac
@ -812,6 +806,7 @@ else
Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;; Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;;
NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;; NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;;
SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;; SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;;
WebAssembly) AC_SUBST(TARGET_HAS_JIT,0) ;;
*) AC_SUBST(TARGET_HAS_JIT,0) ;; *) AC_SUBST(TARGET_HAS_JIT,0) ;;
esac esac
fi fi
@ -1105,7 +1100,7 @@ TARGETS_TO_BUILD=""
AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets],
[Build specific host targets: all or target1,target2,... Valid targets are: [Build specific host targets: all or target1,target2,... Valid targets are:
host, x86, x86_64, sparc, powerpc, arm64, arm, aarch64, mips, hexagon, 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) enableval=all)
if test "$enableval" = host-only ; then if test "$enableval" = host-only ; then
enableval=host enableval=host
@ -1134,6 +1129,7 @@ case "$enableval" in
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;; amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
r600) 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 host) case "$llvm_cv_target_arch" in
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
x86_64) 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" ;; Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
SystemZ) TARGETS_TO_BUILD="SystemZ $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]) ;; *) AC_MSG_ERROR([Can not set target to build]) ;;
esac ;; esac ;;
*) AC_MSG_ERROR([Unrecognized target $a_target]) ;; *) AC_MSG_ERROR([Unrecognized target $a_target]) ;;
@ -1631,7 +1628,7 @@ dnl===-----------------------------------------------------------------------===
AC_CHECK_LIB(m,sin) AC_CHECK_LIB(m,sin)
if test "$llvm_cv_os_type" = "MingW" ; then 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(psapi, main)
AC_CHECK_LIB(shell32, main) AC_CHECK_LIB(shell32, main)
fi 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. 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]) AC_CONFIG_HEADERS([include/llvm/Config/config.h include/llvm/Config/llvm-config.h])
AH_TOP([#ifndef CONFIG_H AH_TOP([#ifndef CONFIG_H
#define CONFIG_H]) #define CONFIG_H
/* Exported configuration */
#include "llvm/Config/llvm-config.h"])
AH_BOTTOM([#endif]) AH_BOTTOM([#endif])
AC_CONFIG_FILES([include/llvm/Config/Targets.def]) AC_CONFIG_FILES([include/llvm/Config/Targets.def])

View File

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

View File

@ -160,6 +160,8 @@ const (
InAllocaAttribute Attribute = 1 << 43 InAllocaAttribute Attribute = 1 << 43
NonNullAttribute Attribute = 1 << 44 NonNullAttribute Attribute = 1 << 44
JumpTableAttribute Attribute = 1 << 45 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)) defer C.free(unsafe.Pointer(cvalue))
C.LLVMAddTargetDependentFunctionAttr(v.C, cattr, cvalue) C.LLVMAddTargetDependentFunctionAttr(v.C, cattr, cvalue)
} }
func (v Value) SetPersonality(p Value) {
C.LLVMSetPersonalityFn(v.C, p.C)
}
// Operations on parameters // Operations on parameters
func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) } func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) }
@ -1723,10 +1728,10 @@ func (b Builder) CreatePtrDiff(lhs, rhs Value, name string) (v Value) {
return 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) cname := C.CString(name)
defer C.free(unsafe.Pointer(cname)) 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 return l
} }

View File

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

View File

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

View File

@ -43,11 +43,11 @@ external run_static_dtors : llexecutionengine -> unit
= "llvm_ee_run_static_dtors" = "llvm_ee_run_static_dtors"
external data_layout : llexecutionengine -> Llvm_target.DataLayout.t external data_layout : llexecutionengine -> Llvm_target.DataLayout.t
= "llvm_ee_get_data_layout" = "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" = "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" = "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" = "llvm_ee_get_function_address"
let add_global_mapping llval ptr ee = 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 get_global_value_address name typ ee =
let vptr = get_global_value_address_ name ee in 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)) let open Ctypes in !@ (coerce (ptr void) (ptr typ) (ptr_of_raw_address vptr))
else else
raise (Error ("Value " ^ name ^ " not found")) raise (Error ("Value " ^ name ^ " not found"))
let get_function_address name typ ee = let get_function_address name typ ee =
let fptr = get_function_address_ name ee in 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) let open Ctypes in coerce (ptr void) typ (ptr_of_raw_address fptr)
else else
raise (Error ("Function " ^ name ^ " not found")) raise (Error ("Function " ^ name ^ " not found"))

View File

@ -371,14 +371,6 @@ class Relocation(LLVMObject):
self.expired = False 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 @CachedProperty
def offset(self): def offset(self):
"""The offset of this relocation, in long bytes.""" """The offset of this relocation, in long bytes."""
@ -498,9 +490,6 @@ def register_library(library):
library.LLVMGetSymbolSize.argtypes = [Symbol] library.LLVMGetSymbolSize.argtypes = [Symbol]
library.LLVMGetSymbolSize.restype = c_uint64 library.LLVMGetSymbolSize.restype = c_uint64
library.LLVMGetRelocationAddress.argtypes = [c_object_p]
library.LLVMGetRelocationAddress.restype = c_uint64
library.LLVMGetRelocationOffset.argtypes = [c_object_p] library.LLVMGetRelocationOffset.argtypes = [c_object_p]
library.LLVMGetRelocationOffset.restype = c_uint64 library.LLVMGetRelocationOffset.restype = c_uint64

View File

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

View File

@ -1,4 +1,3 @@
include(LLVMParseArguments)
include(LLVMProcessSources) include(LLVMProcessSources)
include(LLVM-Config) include(LLVM-Config)
@ -84,25 +83,19 @@ function(add_llvm_symbol_exports target_name export_file)
DEPENDS ${export_file} DEPENDS ${export_file}
VERBATIM VERBATIM
COMMENT "Creating export file for ${target_name}") COMMENT "Creating export file for ${target_name}")
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 set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}") LINK_FLAGS " -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
endif()
else() else()
set(native_export_file "${target_name}.def") 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} add_custom_command(OUTPUT ${native_export_file}
COMMAND ${CMAKE_COMMAND} -E echo "EXPORTS" > ${native_export_file} COMMAND ${PYTHON_EXECUTABLE} -c "import sys;print(''.join(['EXPORTS\\n']+sys.stdin.readlines(),))"
COMMAND ${CAT} ${export_file_nativeslashes} >> ${native_export_file} < ${export_file} > ${native_export_file}
DEPENDS ${export_file} DEPENDS ${export_file}
VERBATIM VERBATIM
COMMENT "Creating export file for ${target_name}") 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 # Pass -O3 to the linker. This enabled different optimizations on different
# linkers. # 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 set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-O3") LINK_FLAGS " -Wl,-O3")
endif() endif()
@ -182,6 +175,9 @@ function(add_link_opts target_name)
# ld64's implementation of -dead_strip breaks tools that use plugins. # ld64's implementation of -dead_strip breaks tools that use plugins.
set_property(TARGET ${target_name} APPEND_STRING PROPERTY set_property(TARGET ${target_name} APPEND_STRING PROPERTY
LINK_FLAGS " -Wl,-dead_strip") 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) elseif(NOT WIN32 AND NOT LLVM_LINKER_IS_GOLD)
# Object files are compiled with -ffunction-data-sections. # Object files are compiled with -ffunction-data-sections.
# Versions of bfd ld < 2.23.1 have a bug in --gc-sections that breaks # 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") set(ARG_PRODUCT_NAME "LLVM")
endif() endif()
set_property(SOURCE ${resource_file}
PROPERTY COMPILE_FLAGS /nologo)
set_property(SOURCE ${resource_file} set_property(SOURCE ${resource_file}
PROPERTY COMPILE_DEFINITIONS PROPERTY COMPILE_DEFINITIONS
"RC_VERSION_FIELD_1=${ARG_VERSION_MAJOR}" "RC_VERSION_FIELD_1=${ARG_VERSION_MAJOR}"
@ -494,11 +492,17 @@ macro(add_llvm_library name)
else() else()
llvm_add_library(${name} ${ARGN}) llvm_add_library(${name} ${ARGN})
endif() endif()
# 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} ) set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} )
endif()
if( EXCLUDE_FROM_ALL ) if( EXCLUDE_FROM_ALL )
set_target_properties( ${name} PROPERTIES EXCLUDE_FROM_ALL ON) 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 (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "LTO")
if(ARG_SHARED OR BUILD_SHARED_LIBS) if(ARG_SHARED OR BUILD_SHARED_LIBS)
if(WIN32 OR CYGWIN) if(WIN32 OR CYGWIN)
@ -672,6 +676,13 @@ macro(add_llvm_target target_name)
set( CURRENT_LLVM_TARGET LLVM${target_name} ) set( CURRENT_LLVM_TARGET LLVM${target_name} )
endmacro(add_llvm_target) 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, # 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 # 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 # 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 "") if("${add_llvm_external_dir}" STREQUAL "")
set(add_llvm_external_dir ${name}) set(add_llvm_external_dir ${name})
endif() endif()
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}") canonicalize_tool_name(${name} nameUPPER)
string(REPLACE "-" "_" nameUNDERSCORE ${name}) if(NOT DEFINED LLVM_TOOL_${nameUPPER}_BUILD)
string(TOUPPER ${nameUNDERSCORE} nameUPPER) option(LLVM_TOOL_${nameUPPER}_BUILD
set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}" "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") CACHE PATH "Path to ${name} source directory")
if (NOT ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} STREQUAL "" mark_as_advanced(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR)
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)
add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir}) add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir})
set(LLVM_TOOL_${nameUPPER}_BUILD Off)
endif() endif()
endif() endif()
endmacro(add_llvm_external_project) endmacro(add_llvm_external_project)
macro(add_llvm_tool_subdirectory name) macro(add_llvm_tool_subdirectory name)
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}") add_llvm_external_project(${name})
add_subdirectory(${name})
endmacro(add_llvm_tool_subdirectory) endmacro(add_llvm_tool_subdirectory)
macro(ignore_llvm_tool_subdirectory name) function(get_project_name_from_src_var var output)
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}") string(REGEX MATCH "LLVM_EXTERNAL_(.*)_SOURCE_DIR"
endmacro(ignore_llvm_tool_subdirectory) 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 "") set(list_of_implicit_subdirs "")
file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*") file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*")
foreach(dir ${sub-dirs}) foreach(dir ${sub-dirs})
if(IS_DIRECTORY "${dir}") if(IS_DIRECTORY "${dir}" AND EXISTS "${dir}/CMakeLists.txt")
list(FIND LLVM_IMPLICIT_PROJECT_IGNORE "${dir}" tool_subdir_ignore) canonicalize_tool_name(${dir} name)
if( tool_subdir_ignore EQUAL -1 if (LLVM_TOOL_${name}_BUILD)
AND EXISTS "${dir}/CMakeLists.txt")
get_filename_component(fn "${dir}" NAME) get_filename_component(fn "${dir}" NAME)
list(APPEND list_of_implicit_subdirs "${fn}") list(APPEND list_of_implicit_subdirs "${fn}")
endif() endif()
@ -723,7 +764,7 @@ function(add_llvm_implicit_external_projects)
foreach(external_proj ${list_of_implicit_subdirs}) foreach(external_proj ${list_of_implicit_subdirs})
add_llvm_external_project("${external_proj}") add_llvm_external_project("${external_proj}")
endforeach() endforeach()
endfunction(add_llvm_implicit_external_projects) endfunction(add_llvm_implicit_projects)
# Generic support for adding a unittest. # Generic support for adding a unittest.
function(add_unittest test_suite test_name) function(add_unittest test_suite test_name)
@ -774,7 +815,7 @@ function(llvm_add_go_executable binary pkgpath)
endforeach(d) endforeach(d)
set(ldflags "${CMAKE_EXE_LINKER_FLAGS}") set(ldflags "${CMAKE_EXE_LINKER_FLAGS}")
add_custom_command(OUTPUT ${binpath} 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} ${ARG_GOFLAGS} build -o ${binpath} ${pkgpath}
DEPENDS llvm-config ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX} DEPENDS llvm-config ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX}
${llvmlibs} ${ARG_DEPENDS} ${llvmlibs} ${ARG_DEPENDS}
@ -845,7 +886,7 @@ endfunction()
# A raw function to create a lit target. This is used to implement the testuite # A raw function to create a lit target. This is used to implement the testuite
# management functions. # management functions.
function(add_lit_target target comment) 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}") set(LIT_ARGS "${ARG_ARGS} ${LLVM_LIT_ARGS}")
separate_arguments(LIT_ARGS) separate_arguments(LIT_ARGS)
if (NOT CMAKE_CFG_INTDIR STREQUAL ".") if (NOT CMAKE_CFG_INTDIR STREQUAL ".")
@ -860,9 +901,9 @@ function(add_lit_target target comment)
foreach(param ${ARG_PARAMS}) foreach(param ${ARG_PARAMS})
list(APPEND LIT_COMMAND --param ${param}) list(APPEND LIT_COMMAND --param ${param})
endforeach() endforeach()
if (ARG_DEFAULT_ARGS) if (ARG_UNPARSED_ARGUMENTS)
add_custom_target(${target} add_custom_target(${target}
COMMAND ${LIT_COMMAND} ${ARG_DEFAULT_ARGS} COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS}
COMMENT "${comment}" COMMENT "${comment}"
${cmake_3_2_USES_TERMINAL} ${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. # A function to add a set of lit test suites to be driven through 'check-*' targets.
function(add_lit_testsuite target comment) 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. # EXCLUDE_FROM_ALL excludes the test ${target} out of check-all.
if(NOT EXCLUDE_FROM_ALL) if(NOT EXCLUDE_FROM_ALL)
# Register the testsuites, params and depends for the global check rule. # 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_PARAMS ${ARG_PARAMS})
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_DEPENDS ${ARG_DEPENDS}) set_property(GLOBAL APPEND PROPERTY LLVM_LIT_DEPENDS ${ARG_DEPENDS})
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_EXTRA_ARGS ${ARG_ARGS}) 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. # Produce a specific suffixed check rule.
add_lit_target(${target} ${comment} add_lit_target(${target} ${comment}
${ARG_DEFAULT_ARGS} ${ARG_UNPARSED_ARGUMENTS}
PARAMS ${ARG_PARAMS} PARAMS ${ARG_PARAMS}
DEPENDS ${ARG_DEPENDS} DEPENDS ${ARG_DEPENDS}
ARGS ${ARG_ARGS} ARGS ${ARG_ARGS}
@ -903,7 +944,7 @@ endfunction()
function(add_lit_testsuites project directory) function(add_lit_testsuites project directory)
if (NOT CMAKE_CONFIGURATION_TYPES) 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) file(GLOB_RECURSE litCfg ${directory}/lit*.cfg)
set(lit_suites) set(lit_suites)
foreach(f ${litCfg}) foreach(f ${litCfg})

View File

@ -2,15 +2,45 @@
INCLUDE(CheckCXXSourceCompiles) INCLUDE(CheckCXXSourceCompiles)
check_function_exists(__atomic_fetch_add_4 HAVE___ATOMIC_FETCH_ADD_4) # Sometimes linking against libatomic is required for atomic ops, if
if( NOT HAVE___ATOMIC_FETCH_ADD_4 ) # 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) check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
set(HAVE_LIBATOMIC False)
if( HAVE_LIBATOMIC ) if( HAVE_LIBATOMIC )
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic") 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()
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(" CHECK_CXX_SOURCE_COMPILES("
#ifdef _MSC_VER #ifdef _MSC_VER
#include <Intrin.h> /* Workaround for PR19898. */ #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 # Pass -Wl,-z,defs. This makes sure all symbols are defined. Otherwise a DSO
# build might work on ELF but fail on MachO/COFF. # 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 ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") AND
NOT LLVM_USE_SANITIZER) NOT LLVM_USE_SANITIZER)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs") 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}") message(STATUS "Building with ${flag}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE)
set(CMAKE_C_FLAGS "${CMAKE_C_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() else()
message(WARNING "${flag} is not supported.") message(WARNING "${flag} is not supported.")
endif() endif()
@ -307,10 +308,12 @@ if( MSVC )
-wd4611 # Suppress 'interaction between '_setjmp' and C++ object destruction is non-portable' -wd4611 # Suppress 'interaction between '_setjmp' and C++ object destruction is non-portable'
-wd4805 # Suppress 'unsafe mix of type <type> and type <type> in operation' -wd4805 # Suppress 'unsafe mix of type <type> and type <type> in operation'
-wd4204 # Suppress 'nonstandard extension used : non-constant aggregate initializer' -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 # 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. # avoid unwanted alignment warnings.
# When we switch to requiring a version of MSVC that supports the 'alignas' # When we switch to requiring a version of MSVC that supports the 'alignas'
# specifier (MSVC 2015?) this warning can be re-enabled. # 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) $(error llvm-config --libs failed)
endif 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 ifndef LLVM_LIBS_TO_EXPORT
$(error LLVM_LIBS_TO_EXPORT cannot be empty) $(error LLVM_LIBS_TO_EXPORT cannot be empty)
endif endif
@ -54,11 +60,27 @@ endif
OBJMODS := LLVMConfig.cmake LLVMConfigVersion.cmake LLVMExports.cmake 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) $(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeFrag)
$(Echo) 'Generating LLVM CMake package config file' $(Echo) 'Generating LLVM CMake package config file'
$(Verb) ( \ $(Verb) ( \
cat $< | sed \ 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_MAJOR@/'"$(LLVM_VERSION_MAJOR)"'/' \
-e 's/@LLVM_VERSION_MINOR@/'"$(LLVM_VERSION_MINOR)"'/' \ -e 's/@LLVM_VERSION_MINOR@/'"$(LLVM_VERSION_MINOR)"'/' \
-e 's/@LLVM_VERSION_PATCH@/'"$(LLVM_VERSION_PATCH)"'/' \ -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_UNIX@/'"$(LLVM_ON_UNIX)"'/' \
-e 's/@LLVM_ON_WIN32@/'"$(LLVM_ON_WIN32)"'/' \ -e 's/@LLVM_ON_WIN32@/'"$(LLVM_ON_WIN32)"'/' \
-e 's/@LLVM_LIBDIR_SUFFIX@//' \ -e 's/@LLVM_LIBDIR_SUFFIX@//' \
-e 's/@LLVM_CONFIG_INCLUDE_DIRS@/'"$(subst /,\/,$(PROJ_includedir))"'/' \ -e 's#@LLVM_CONFIG_INCLUDE_DIRS@#$${LLVM_INSTALL_PREFIX}/include#' \
-e 's/@LLVM_CONFIG_LIBRARY_DIRS@/'"$(subst /,\/,$(PROJ_libdir))"'/' \ -e 's#@LLVM_CONFIG_LIBRARY_DIRS@#$${_LLVM_LIBRARY_DIR}#' \
-e 's/@LLVM_CONFIG_CMAKE_DIR@/'"$(subst /,\/,$(PROJ_cmake))"'/' \ -e 's#@LLVM_CONFIG_CMAKE_DIR@#$${_LLVM_CMAKE_DIR}#' \
-e 's/@LLVM_CONFIG_TOOLS_BINARY_DIR@/'"$(subst /,\/,$(PROJ_bindir))"'/' \ -e 's#@LLVM_CONFIG_TOOLS_BINARY_DIR@#$${LLVM_INSTALL_PREFIX}/bin#' \
-e 's/@LLVM_CONFIG_EXPORTS_FILE@/$${LLVM_CMAKE_DIR}\/LLVMExports.cmake/' \ -e 's/@LLVM_CONFIG_EXPORTS_FILE@/$${LLVM_CMAKE_DIR}\/LLVMExports.cmake/' \
-e 's/@all_llvm_lib_deps@//' \ -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' $(Echo) 'Generating LLVM CMake package version file'
$(Verb) cat $< | sed \ $(Verb) cat $< | sed \
-e 's/@PACKAGE_VERSION@/'"$(LLVMVersion)"'/' \ -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)"'/' \ -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' $(Echo) 'Generating LLVM CMake target exports file'
$(Verb) ( \ $(Verb) ( \
echo '# LLVM CMake target exports. Do not include directly.' && \ echo '# LLVM CMake target exports. Do not include directly.' && \
for lib in $(LLVM_LIBS_TO_EXPORT); do \ for lib in $(LLVM_LIBS_TO_EXPORT); do \
echo 'add_library('"$$lib"' STATIC IMPORTED)' && \ 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 && \ done && \
cat "$(LLVMBuildCMakeExportsFrag)" && \ cat "$(LLVMBuildCMakeExportsFrag)" && \
echo 'set_property(TARGET LLVMSupport APPEND PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES '"$(subst -l,,$(LIBS))"')' \ 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 #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # 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/>. # Report bugs to <http://llvm.org/bugs/>.
# #
@ -561,8 +561,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
# Identity of this package. # Identity of this package.
PACKAGE_NAME='LLVM' PACKAGE_NAME='LLVM'
PACKAGE_TARNAME='llvm' PACKAGE_TARNAME='llvm'
PACKAGE_VERSION='3.7.0svn' PACKAGE_VERSION='3.8.0svn'
PACKAGE_STRING='LLVM 3.7.0svn' PACKAGE_STRING='LLVM 3.8.0svn'
PACKAGE_BUGREPORT='http://llvm.org/bugs/' PACKAGE_BUGREPORT='http://llvm.org/bugs/'
ac_unique_file="lib/IR/Module.cpp" 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. # 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. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF 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]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1399,7 +1399,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of LLVM 3.7.0svn:";; short | recursive ) echo "Configuration of LLVM 3.8.0svn:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1463,7 +1463,7 @@ Optional Features:
target1,target2,... Valid targets are: host, x86, target1,target2,... Valid targets are: host, x86,
x86_64, sparc, powerpc, arm64, arm, aarch64, mips, x86_64, sparc, powerpc, arm64, arm, aarch64, mips,
hexagon, xcore, msp430, nvptx, systemz, r600, bpf, hexagon, xcore, msp430, nvptx, systemz, r600, bpf,
and cpp (default=all) wasm, and cpp (default=all)
--enable-experimental-targets --enable-experimental-targets
Build experimental host targets: disable or Build experimental host targets: disable or
target1,target2,... (default=disable) target1,target2,... (default=disable)
@ -1583,7 +1583,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
LLVM configure 3.7.0svn LLVM configure 3.8.0svn
generated by GNU Autoconf 2.60 generated by GNU Autoconf 2.60
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 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 This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. 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 generated by GNU Autoconf 2.60. Invocation command line was
$ $0 $@ $ $0 $@
@ -1954,7 +1954,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
LLVM_VERSION_MAJOR=3 LLVM_VERSION_MAJOR=3
LLVM_VERSION_MINOR=7 LLVM_VERSION_MINOR=8
LLVM_VERSION_PATCH=0 LLVM_VERSION_PATCH=0
LLVM_VERSION_SUFFIX=svn LLVM_VERSION_SUFFIX=svn
@ -2033,24 +2033,9 @@ echo "$as_me: error: Already configured in ${srcdir}" >&2;}
fi fi
if test ${srcdir} == "." ; then if test ${srcdir} == "." ; then
{ echo "$as_me:$LINENO: WARNING: **************************************************************************************" >&5 { { echo "$as_me:$LINENO: error: In-source builds are not allowed. Please configure from a separate build directory!" >&5
echo "$as_me: WARNING: **************************************************************************************" >&2;} echo "$as_me: error: In-source builds are not allowed. Please configure from a separate build directory!" >&2;}
{ echo "$as_me:$LINENO: WARNING: * *" >&5 { (exit 1); exit 1; }; }
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;}
fi fi
: ${CFLAGS=} : ${CFLAGS=}
@ -4207,6 +4192,7 @@ else
hexagon-*) llvm_cv_target_arch="Hexagon" ;; hexagon-*) llvm_cv_target_arch="Hexagon" ;;
nvptx-*) llvm_cv_target_arch="NVPTX" ;; nvptx-*) llvm_cv_target_arch="NVPTX" ;;
s390x-*) llvm_cv_target_arch="SystemZ" ;; s390x-*) llvm_cv_target_arch="SystemZ" ;;
wasm*-*) llvm_cv_target_arch="WebAssembly" ;;
*) llvm_cv_target_arch="Unknown" ;; *) llvm_cv_target_arch="Unknown" ;;
esac esac
fi fi
@ -4243,6 +4229,7 @@ case $host in
msp430-*) host_arch="MSP430" ;; msp430-*) host_arch="MSP430" ;;
hexagon-*) host_arch="Hexagon" ;; hexagon-*) host_arch="Hexagon" ;;
s390x-*) host_arch="SystemZ" ;; s390x-*) host_arch="SystemZ" ;;
wasm*-*) host_arch="WebAssembly" ;;
*) host_arch="Unknown" ;; *) host_arch="Unknown" ;;
esac esac
@ -5169,6 +5156,8 @@ else
NVPTX) TARGET_HAS_JIT=0 NVPTX) TARGET_HAS_JIT=0
;; ;;
SystemZ) TARGET_HAS_JIT=1 SystemZ) TARGET_HAS_JIT=1
;;
WebAssembly) TARGET_HAS_JIT=0
;; ;;
*) TARGET_HAS_JIT=0 *) TARGET_HAS_JIT=0
;; ;;
@ -5667,6 +5656,7 @@ case "$enableval" in
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;; systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;; amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
r600) 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 host) case "$llvm_cv_target_arch" in
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
x86_64) 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" ;; Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;; NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
SystemZ) TARGETS_TO_BUILD="SystemZ $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:$LINENO: error: Can not set target to build" >&5
echo "$as_me: error: Can not set target to build" >&2;} echo "$as_me: error: Can not set target to build" >&2;}
{ (exit 1); exit 1; }; } ;; { (exit 1); exit 1; }; } ;;
@ -8733,6 +8724,87 @@ _ACEOF
fi 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 "$as_me:$LINENO: checking for main in -lpsapi" >&5
echo $ECHO_N "checking for main in -lpsapi... $ECHO_C" >&6; } echo $ECHO_N "checking for main in -lpsapi... $ECHO_C" >&6; }
if test "${ac_cv_lib_psapi_main+set}" = set; then 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 # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" 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 generated by GNU Autoconf 2.60. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -18591,7 +18663,7 @@ Report bugs to <bug-autoconf@gnu.org>."
_ACEOF _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF cat >>$CONFIG_STATUS <<_ACEOF
ac_cs_version="\\ ac_cs_version="\\
LLVM config.status 3.7.0svn LLVM config.status 3.8.0svn
configured by $0, generated by GNU Autoconf 2.60, configured by $0, generated by GNU Autoconf 2.60,
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" 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 v1, v2, v3
v_mul_i32_i24_e32 v1, v2, v3 v_mul_i32_i24_e32 v1, v2, v3
v_mul_i32_i24_e64 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,7 +286,7 @@ Mod/Ref result, simply return whatever the superclass computes. For example:
.. code-block:: c++ .. code-block:: c++
AliasAnalysis::AliasResult alias(const Value *V1, unsigned V1Size, AliasResult alias(const Value *V1, unsigned V1Size,
const Value *V2, unsigned V2Size) { const Value *V2, unsigned V2Size) {
if (...) if (...)
return NoAlias; return NoAlias;

View File

@ -741,7 +741,7 @@ global variable. The operand fields are:
MODULE_CODE_FUNCTION Record 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 The ``FUNCTION`` record (code 8) marks the declaration or definition of a
function. The operand fields are: 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, * *prefixdata*: If non-zero, the value index of the prefix data for this function,
plus 1. plus 1.
* *personalityfn*: If non-zero, the value index of the personality function for this function,
plus 1.
MODULE_CODE_ALIAS Record MODULE_CODE_ALIAS Record
^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^

View File

@ -327,8 +327,8 @@ LLVM-specific variables
**LLVM_USE_SANITIZER**:STRING **LLVM_USE_SANITIZER**:STRING
Define the sanitizer used to build LLVM binaries and tests. Possible values Define the sanitizer used to build LLVM binaries and tests. Possible values
are ``Address``, ``Memory``, ``MemoryWithOrigins`` and ``Undefined``. are ``Address``, ``Memory``, ``MemoryWithOrigins``, ``Undefined``, ``Thread``,
Defaults to empty string. and ``Address;Undefined``. Defaults to empty string.
**LLVM_PARALLEL_COMPILE_JOBS**:STRING **LLVM_PARALLEL_COMPILE_JOBS**:STRING
Define the maximum number of concurrent compilation jobs. 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 remove_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html
COMMAND ${CMAKE_COMMAND} -E make_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 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}) 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 ``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 (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 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 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 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 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 SelectionDAG at specific times (if you only get errors printed to the console
while using this, you probably `need to configure your 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 * ``-view-dag-combine1-dags`` displays the DAG after being built, before the
first optimization pass. first optimization pass.

View File

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

View File

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

View File

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

View File

@ -26,5 +26,5 @@ OPTIONS
EXIT STATUS EXIT STATUS
----------- -----------
:program:`llvm-dwarfdump` returns 0. Other exit codes imply internal :program:`llvm-dwarfdump` returns 0 if the input files were parsed and dumped
program error. 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 loaded options:
Dynamically adding command line options Dynamically adding command line options
---------------------------------------
.. todo:: .. 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 encoding, optimizing for the case where values are small
(1 byte for values less than 128). (1 byte for values less than 128).
.. _strings: .. _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 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 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 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. 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 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 and a pointer to the parent function's stack frame as the second
argument. The catch handler uses the `llvm.recoverframe argument. The catch handler uses the `llvm.localrecover
<LangRef.html#llvm-frameallocate-and-llvm-framerecover-intrinsics>`_ to get a <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 pointer to a frame allocation block that is created in the parent frame using
the `llvm.allocateframe the `llvm.localescape
<LangRef.html#llvm-frameallocate-and-llvm-framerecover-intrinsics>`_ intrinsic. <LangRef.html#llvm-localescape-and-llvm-localrecover-intrinsics>`_ intrinsic.
The ``WinEHPrepare`` pass will have created a structure definition for the 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 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 (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 A code of ``i32 1`` indicates a catch action, which expects three additional
arguments. Different EH schemes give different meanings to the three arguments, arguments. Different EH schemes give different meanings to the three arguments,
but the first argument indicates whether the catch should fire, the second is 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. to catch the exception.
For Windows C++ exception handling, the first argument for a catch handler is a 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 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 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. 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 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] { FunctionFaultInfo[NumFaultingPCs] {
uint32 : FaultKind = FaultMaps::FaultingLoad (only legal value currently) uint32 : FaultKind = FaultMaps::FaultingLoad (only legal value currently)
uint32 : FaultingPCOffset 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 .. 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 % tar -xvjf gcc-4.8.2.tar.bz2
% cd gcc-4.8.2 % cd gcc-4.8.2
% ./contrib/download_prerequisites % ./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 In addition, the version numbers of all the Bugzilla components must be updated
for the next release. for the next release.
Build the LLVM Release Candidates Tagging the LLVM Release Candidates
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Create release candidates for ``llvm``, ``clang``, ``dragonegg``, and the LLVM Tag release candidates using the tag.sh script in utils/release.
``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:
:: ::
$ svn mkdir https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ $ ./tag.sh -release X.Y.Z -rc $RC
$ 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`).
The Release Manager may supply pre-packaged source tarballs for users. This can 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 $ ./export.sh -release X.Y.Z -rc $RC
$ 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
$ tar -cvf - llvm-X.Yrc1 | gzip > llvm-X.Yrc1.src.tar.gz This will generate source tarballs for each LLVM project being validated, which
$ tar -cvf - clang-X.Yrc1 | gzip > clang-X.Yrc1.src.tar.gz can be uploaded to the website for further testing.
$ 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
Building the Release Building the Release
-------------------- --------------------
@ -384,21 +357,11 @@ mainline into the release branch.
Tag the LLVM Final Release 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 \ $ ./tag.sh -release X.Y.Z -final
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
Update the LLVM Demo Page 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) (cd pcre; ./autogen.sh; CC="clang -fsanitize=address $COV_FLAGS" ./configure --prefix=`pwd`/../inst && make -j && make install)
# Build lib/Fuzzer files. # Build lib/Fuzzer files.
clang -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer 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 cat << EOF > pcre_fuzzer.cc
#include <string.h> #include <string.h>
#include "pcre2posix.h" #include "pcre2posix.h"

View File

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

View File

@ -1,12 +1,12 @@
====================== ======================
LLVM 3.7 Release Notes LLVM 3.8 Release Notes
====================== ======================
.. contents:: .. contents::
:local: :local:
.. warning:: .. 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 prefer the `LLVM 3.6 Release Notes <http://llvm.org/releases/3.6.0/docs
/ReleaseNotes.html>`_. /ReleaseNotes.html>`_.
@ -15,7 +15,7 @@ Introduction
============ ============
This document contains the release notes for the LLVM Compiler Infrastructure, 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 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 some of the current users of the code. All LLVM releases may be downloaded
from the `LLVM releases web site <http://llvm.org/releases/>`_. 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 functionality, or simply have a lot to talk about), see the `NOTE` below
for adding a new subsection. 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 ... * ... next change ...
.. NOTE .. NOTE
@ -89,12 +77,12 @@ Changes to the OCaml bindings
During this release ... 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 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 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 * 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 intrinsic's callsite. Variants of the intrinsic with non-void return
type also return a value according to calling convention. type also return a value according to calling convention.
On PowerPC, note that ``<target>`` must be the actual intended target of On PowerPC, note that ``<target>`` must be the ABI function pointer for the
the indirect call. Specifically, even when compiling for the ELF V1 ABI, intended target of the indirect call. Specifically, when compiling for the
``<target>`` is not the function-descriptor address normally used as the C/C++ ELF V1 ABI, ``<target>`` is the function-descriptor address normally used as
function-pointer representation. As a result, the call target must be local the C/C++ function-pointer representation.
because no adjustment or restoration of the TOC pointer (in register r2) will
be performed.
Requesting zero patch point arguments is valid. In this case, all Requesting zero patch point arguments is valid. In this case, all
variable operands are handled just like 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 transformations must not substitute the alloca with any intervening
value. This can be verified by the runtime simply by checking that the value. This can be verified by the runtime simply by checking that the
stack map's location is a Direct location type. 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 calling sequence specific to their runtime before executing the
generated machine code. There are no guarantees with respect to the generated machine code. There are no guarantees with respect to the
alignment of the nop sequence. Unlike :doc:`StackMaps` statepoints do 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 The 'target' operand is the function actually being called. The
target can be specified as either a symbolic LLVM function, or as an target can be specified as either a symbolic LLVM function, or as an
arbitrary Value of appropriate function type. Note that the function arbitrary Value of appropriate function type. Note that the function
type must match the signature of the callee and the types of the 'call 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' parameters' arguments.
has to be the constant pointer null of the appropriate function type.
The '#call args' operand is the number of arguments to the actual The '#call args' operand is the number of arguments to the actual
call. It must exactly match the number of arguments passed in the 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. 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 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. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '3.7' version = '3.8'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '3.7' release = '3.8'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

View File

@ -395,9 +395,8 @@ argument allocas in ``PrototypeAST::CreateArgumentAllocas``.
DIScope *Scope = KSDbgInfo.LexicalBlocks.back(); DIScope *Scope = KSDbgInfo.LexicalBlocks.back();
DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(), DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(),
KSDbgInfo.TheCU.getDirectory()); KSDbgInfo.TheCU.getDirectory());
DILocalVariable D = DBuilder->createLocalVariable( DILocalVariable D = DBuilder->createParameterVariable(
dwarf::DW_TAG_arg_variable, Scope, Args[Idx], Unit, Line, Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true);
KSDbgInfo.getDoubleTy(), Idx);
Instruction *Call = DBuilder->insertDeclare( Instruction *Call = DBuilder->insertDeclare(
Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock()); 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_AMD64
, IMAGE_FILE_MACHINE_ARM , IMAGE_FILE_MACHINE_ARM
, IMAGE_FILE_MACHINE_ARMNT , IMAGE_FILE_MACHINE_ARMNT
, IMAGE_FILE_MACHINE_ARM64
, IMAGE_FILE_MACHINE_EBC , IMAGE_FILE_MACHINE_EBC
, IMAGE_FILE_MACHINE_I386 , IMAGE_FILE_MACHINE_I386
, IMAGE_FILE_MACHINE_IA64 , 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 // Set up the optimizer pipeline. Start with registering info about how the
// target lays out data structures. // target lays out data structures.
OpenModule->setDataLayout(*NewEngine->getDataLayout()); OpenModule->setDataLayout(NewEngine->getDataLayout());
// Provide basic AliasAnalysis support for GVN. // Provide basic AliasAnalysis support for GVN.
FPM->add(createBasicAliasAnalysisPass()); FPM->add(createBasicAliasAnalysisPass());
// Promote allocas to registers. // Promote allocas to registers.

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -81,7 +81,6 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI);
uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI); uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI);
// RelocationRef accessors // RelocationRef accessors
uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI);
uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI); uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI);
LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI); LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI);
uint64_t LLVMGetRelocationType(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 * \since prior to LTO_API_VERSION=3
@ -63,7 +63,8 @@ typedef enum {
LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000, LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000,
LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800, LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800,
LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800, LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800,
LTO_SYMBOL_COMDAT = 0x00004000 LTO_SYMBOL_COMDAT = 0x00004000,
LTO_SYMBOL_ALIAS = 0x00008000
} lto_symbol_attributes; } 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 * The linker options may consist of multiple flags. It is the linker's
*/ * responsibility to split the flags using a platform-specific mechanism.
extern unsigned int
lto_module_get_num_deplibs(lto_module_t mod);
/**
* Returns the ith dependent library in the module.
* *
* \since LTO_API_VERSION=8 * \since LTO_API_VERSION=16
*/ */
extern const char* extern const char*
lto_module_get_deplib(lto_module_t mod, unsigned int index); lto_module_get_linkeropts(lto_module_t mod);
/**
* 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);
/** /**

View File

@ -276,6 +276,10 @@ public:
/// \param isIEEE - If 128 bit number, select between PPC and IEEE /// \param isIEEE - If 128 bit number, select between PPC and IEEE
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false); 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, /// 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. /// the validity of the less-than relationship.
/// ///
/// \returns true if *this < RHS when considered unsigned. /// \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 /// \brief Signed less than comparison
/// ///
@ -1054,7 +1056,9 @@ public:
/// the validity of the less-than relationship. /// the validity of the less-than relationship.
/// ///
/// \returns true if *this < RHS when considered signed. /// \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 /// \brief Unsigned less or equal comparison
/// ///
@ -1070,7 +1074,7 @@ public:
/// the validity of the less-or-equal relationship. /// the validity of the less-or-equal relationship.
/// ///
/// \returns true if *this <= RHS when considered unsigned. /// \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 /// \brief Signed less or equal comparison
/// ///
@ -1086,7 +1090,7 @@ public:
/// validity of the less-or-equal relationship. /// validity of the less-or-equal relationship.
/// ///
/// \returns true if *this <= RHS when considered signed. /// \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 /// \brief Unsigned greather than comparison
/// ///
@ -1102,7 +1106,9 @@ public:
/// the validity of the greater-than relationship. /// the validity of the greater-than relationship.
/// ///
/// \returns true if *this > RHS when considered unsigned. /// \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 /// \brief Signed greather than comparison
/// ///
@ -1118,7 +1124,9 @@ public:
/// the validity of the greater-than relationship. /// the validity of the greater-than relationship.
/// ///
/// \returns true if *this > RHS when considered signed. /// \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 /// \brief Unsigned greater or equal comparison
/// ///
@ -1134,7 +1142,7 @@ public:
/// the validity of the greater-or-equal relationship. /// the validity of the greater-or-equal relationship.
/// ///
/// \returns true if *this >= RHS when considered unsigned. /// \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 /// \brief Signed greather or equal comparison
/// ///
@ -1150,7 +1158,7 @@ public:
/// the validity of the greater-or-equal relationship. /// the validity of the greater-or-equal relationship.
/// ///
/// \returns true if *this >= RHS when considered signed. /// \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 /// This operation tests if there are any pairs of corresponding bits
/// between this APInt and RHS that are both set. /// between this APInt and RHS that are both set.

View File

@ -33,6 +33,15 @@ public:
explicit APSInt(APInt I, bool isUnsigned = true) explicit APSInt(APInt I, bool isUnsigned = true)
: APInt(std::move(I)), IsUnsigned(isUnsigned) {} : 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) { APSInt &operator=(APInt RHS) {
// Retain our current sign. // Retain our current sign.
APInt::operator=(std::move(RHS)); APInt::operator=(std::move(RHS));

View File

@ -85,7 +85,7 @@ namespace llvm {
/// Construct an ArrayRef from a std::initializer_list. /// Construct an ArrayRef from a std::initializer_list.
/*implicit*/ ArrayRef(const std::initializer_list<T> &Vec) /*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()) {} Length(Vec.size()) {}
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to /// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
@ -286,6 +286,11 @@ namespace llvm {
return MutableArrayRef<T>(data()+N, M); 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 /// @name Operator Overloads
/// @{ /// @{

View File

@ -14,6 +14,8 @@
#ifndef LLVM_ADT_DENSEMAPINFO_H #ifndef LLVM_ADT_DENSEMAPINFO_H
#define 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/PointerLikeTypeTraits.h"
#include "llvm/Support/type_traits.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 } // end namespace llvm
#endif #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); 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> // Extra additions to <utility>
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -44,6 +44,8 @@ public:
typedef Vector vector_type; typedef Vector vector_type;
typedef typename vector_type::const_iterator iterator; typedef typename vector_type::const_iterator iterator;
typedef typename vector_type::const_iterator const_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; typedef typename vector_type::size_type size_type;
/// \brief Construct an empty SetVector /// \brief Construct an empty SetVector
@ -85,6 +87,26 @@ public:
return vector_.end(); 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. /// \brief Return the last element of the SetVector.
const T &back() const { const T &back() const {
assert(!empty() && "Cannot call back() on empty SetVector!"); assert(!empty() && "Cannot call back() on empty SetVector!");

View File

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

View File

@ -85,7 +85,9 @@ public:
spir64, // SPIR: standard portable IR for OpenCL 64-bit version spir64, // SPIR: standard portable IR for OpenCL 64-bit version
kalimba, // Kalimba: generic kalimba kalimba, // Kalimba: generic kalimba
shave, // SHAVE: Movidius vector VLIW processors shave, // SHAVE: Movidius vector VLIW processors
LastArchType = shave wasm32, // WebAssembly with 32-bit pointers
wasm64, // WebAssembly with 64-bit pointers
LastArchType = wasm64
}; };
enum SubArchType { enum SubArchType {
NoSubArch, NoSubArch,
@ -168,7 +170,8 @@ public:
MSVC, MSVC,
Itanium, Itanium,
Cygnus, Cygnus,
LastEnvironmentType = Cygnus AMDOpenCL,
LastEnvironmentType = AMDOpenCL
}; };
enum ObjectFormatType { enum ObjectFormatType {
UnknownObjectFormat, UnknownObjectFormat,
@ -567,6 +570,22 @@ public:
/// architecture if no such variant can be found. /// architecture if no such variant can be found.
llvm::Triple get64BitArchVariant() const; 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. /// 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 /// \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 // http://en.wikipedia.org/wiki/Levenshtein_distance
// //
// Although the algorithm is typically described using an m x n // Although the algorithm is typically described using an m x n
// array, only two rows are used at a time, so this implementation // array, only one row plus one element are used at a time, so this
// just keeps two separate vectors for those two rows. // 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 m = FromArray.size();
typename ArrayRef<T>::size_type n = ToArray.size(); typename ArrayRef<T>::size_type n = ToArray.size();
const unsigned SmallBufferSize = 64; const unsigned SmallBufferSize = 64;
unsigned SmallBuffer[SmallBufferSize]; unsigned SmallBuffer[SmallBufferSize];
std::unique_ptr<unsigned[]> Allocated; std::unique_ptr<unsigned[]> Allocated;
unsigned *Previous = SmallBuffer; unsigned *Row = SmallBuffer;
if (2*(n + 1) > SmallBufferSize) { if (n + 1 > SmallBufferSize) {
Previous = new unsigned [2*(n+1)]; Row = new unsigned[n + 1];
Allocated.reset(Previous); Allocated.reset(Row);
} }
unsigned *Current = Previous + (n + 1);
for (unsigned i = 0; i <= n; ++i) for (unsigned i = 1; i <= n; ++i)
Previous[i] = i; Row[i] = i;
for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) { for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) {
Current[0] = y; Row[0] = y;
unsigned BestThisRow = Current[0]; unsigned BestThisRow = Row[0];
unsigned Previous = y - 1;
for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) { for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) {
int OldRow = Row[x];
if (AllowReplacements) { if (AllowReplacements) {
Current[x] = std::min( Row[x] = std::min(
Previous[x-1] + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u), Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
std::min(Current[x-1], Previous[x])+1); std::min(Row[x-1], Row[x])+1);
} }
else { else {
if (FromArray[y-1] == ToArray[x-1]) Current[x] = Previous[x-1]; if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous;
else Current[x] = std::min(Current[x-1], Previous[x]) + 1; 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) if (MaxEditDistance && BestThisRow > MaxEditDistance)
return MaxEditDistance + 1; return MaxEditDistance + 1;
unsigned *tmp = Current;
Current = Previous;
Previous = tmp;
} }
unsigned Result = Previous[n]; unsigned Result = Row[n];
return Result; return Result;
} }

View File

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

View File

@ -20,6 +20,7 @@
#define LLVM_ADT_ITERATOR_RANGE_H #define LLVM_ADT_ITERATOR_RANGE_H
#include <utility> #include <utility>
#include <iterator>
namespace llvm { namespace llvm {
@ -32,6 +33,12 @@ class iterator_range {
IteratorT begin_iterator, end_iterator; IteratorT begin_iterator, end_iterator;
public: 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) iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
: begin_iterator(std::move(begin_iterator)), : begin_iterator(std::move(begin_iterator)),
end_iterator(std::move(end_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) { 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)); 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 #endif

View File

@ -16,11 +16,12 @@
// which automatically provides functionality for the entire suite of client // which automatically provides functionality for the entire suite of client
// APIs. // 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 // 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 maximum size (in address units) of the memory region, or
// the size is not known. The TBAA tag identifies the "type" of the memory // MemoryLocation::UnknownSize if the size is not known. The TBAA tag
// reference; see the TypeBasedAliasAnalysis class for details. // identifies the "type" of the memory reference; see the
// TypeBasedAliasAnalysis class for details.
// //
// Some non-obvious details include: // Some non-obvious details include:
// - Pointers that point to two completely different objects in memory never // - Pointers that point to two completely different objects in memory never
@ -54,6 +55,106 @@ class AnalysisUsage;
class MemTransferInst; class MemTransferInst;
class MemIntrinsic; class MemIntrinsic;
class DominatorTree; 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 { class AliasAnalysis {
protected: protected:
@ -80,11 +181,6 @@ public:
AliasAnalysis() : DL(nullptr), TLI(nullptr), AA(nullptr) {} AliasAnalysis() : DL(nullptr), TLI(nullptr), AA(nullptr) {}
virtual ~AliasAnalysis(); // We want to be subclassed 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 /// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
/// object, or null if no TargetLibraryInfo object is available. /// object, or null if no TargetLibraryInfo object is available.
/// ///
@ -96,242 +192,284 @@ public:
uint64_t getTypeStoreSize(Type *Ty); uint64_t getTypeStoreSize(Type *Ty);
//===--------------------------------------------------------------------===// //===--------------------------------------------------------------------===//
/// Alias Queries... /// \name Alias Queries
/// /// @{
/// Legacy typedef for the AA location object. New code should use \c /// The main low level interface to the alias analysis implementation.
/// 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.
/// Returns an AliasResult indicating whether the two pointers are aliased to /// 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. /// 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. /// A convenience wrapper around the primary \c alias interface.
AliasResult alias(const Value *V1, uint64_t V1Size, AliasResult alias(const Value *V1, uint64_t V1Size, const Value *V2,
const Value *V2, uint64_t V2Size) { uint64_t V2Size) {
return alias(Location(V1, V1Size), Location(V2, 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) { 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 /// A trivial helper function to check to see if the specified pointers are
/// pointers are no-alias. /// no-alias.
bool isNoAlias(const Location &LocA, const Location &LocB) { bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
return alias(LocA, LocB) == NoAlias; return alias(LocA, LocB) == NoAlias;
} }
/// isNoAlias - A convenience wrapper. /// A convenience wrapper around the \c isNoAlias helper interface.
bool isNoAlias(const Value *V1, uint64_t V1Size, bool isNoAlias(const Value *V1, uint64_t V1Size, const Value *V2,
const Value *V2, uint64_t V2Size) { uint64_t V2Size) {
return isNoAlias(Location(V1, V1Size), Location(V2, 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) { bool isNoAlias(const Value *V1, const Value *V2) {
return isNoAlias(Location(V1), Location(V2)); return isNoAlias(MemoryLocation(V1), MemoryLocation(V2));
} }
/// isMustAlias - A convenience wrapper. /// A trivial helper function to check to see if the specified pointers are
bool isMustAlias(const Location &LocA, const Location &LocB) { /// must-alias.
bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
return alias(LocA, LocB) == MustAlias; 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) { bool isMustAlias(const Value *V1, const Value *V2) {
return alias(V1, 1, V2, 1) == MustAlias; return alias(V1, 1, V2, 1) == MustAlias;
} }
/// pointsToConstantMemory - If the specified memory location is /// Checks whether the given location points to constant memory, or if
/// known to be constant, return true. If OrLocal is true and the /// \p OrLocal is true whether it points to a local alloca.
/// specified memory location is known to be "local" (derived from virtual bool pointsToConstantMemory(const MemoryLocation &Loc,
/// an alloca), return true. Otherwise return false.
virtual bool pointsToConstantMemory(const Location &Loc,
bool OrLocal = false); bool OrLocal = false);
/// pointsToConstantMemory - A convenient wrapper. /// A convenience wrapper around the primary \c pointsToConstantMemory
/// interface.
bool pointsToConstantMemory(const Value *P, bool OrLocal = false) { 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.
/// ///
/// Note that if the call only reads from known-constant memory, it is also
/// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are /// legal to return true. Also, calls that unwind the stack are legal for
/// bits which may be or'd together. /// this predicate.
///
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.
/// ///
/// Many optimizations (such as CSE and LICM) can be performed on such calls /// Many optimizations (such as CSE and LICM) can be performed on such calls
/// without worrying about aliasing properties, and many calls have this /// without worrying about aliasing properties, and many calls have this
/// property (e.g. calls to 'sin' and 'cos'). /// property (e.g. calls to 'sin' and 'cos').
/// ///
/// This property corresponds to the GCC 'const' attribute. /// This property corresponds to the GCC 'const' attribute.
///
bool doesNotAccessMemory(ImmutableCallSite CS) { bool doesNotAccessMemory(ImmutableCallSite CS) {
return getModRefBehavior(CS) == DoesNotAccessMemory; return getModRefBehavior(CS) == FMRB_DoesNotAccessMemory;
} }
/// doesNotAccessMemory - If the specified function is known to never read or /// Checks if the specified function is known to never read or write memory.
/// write memory, return true. For use when the call site is not known.
/// ///
/// 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) { 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 /// Checks if the specified call is known to only read from non-volatile
/// non-volatile memory (or not access memory at all), return true. Calls /// memory (or not access memory at all).
/// that unwind the stack are legal for this predicate. ///
/// Calls that unwind the stack are legal for this predicate.
/// ///
/// This property allows many common optimizations to be performed in the /// This property allows many common optimizations to be performed in the
/// absence of interfering store instructions, such as CSE of strlen calls. /// absence of interfering store instructions, such as CSE of strlen calls.
/// ///
/// This property corresponds to the GCC 'pure' attribute. /// This property corresponds to the GCC 'pure' attribute.
///
bool onlyReadsMemory(ImmutableCallSite CS) { bool onlyReadsMemory(ImmutableCallSite CS) {
return onlyReadsMemory(getModRefBehavior(CS)); return onlyReadsMemory(getModRefBehavior(CS));
} }
/// onlyReadsMemory - If the specified function is known to only read from /// Checks if the specified function is known to only read from non-volatile
/// non-volatile memory (or not access memory at all), return true. For use /// memory (or not access memory at all).
/// when the call site is not known.
/// ///
/// 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) { bool onlyReadsMemory(const Function *F) {
return onlyReadsMemory(getModRefBehavior(F)); return onlyReadsMemory(getModRefBehavior(F));
} }
/// onlyReadsMemory - Return true if functions with the specified behavior are /// Checks if functions with the specified behavior are known to only read
/// known to only read from non-volatile memory (or not access memory at all). /// from non-volatile memory (or not access memory at all).
/// static bool onlyReadsMemory(FunctionModRefBehavior MRB) {
static bool onlyReadsMemory(ModRefBehavior MRB) { return !(MRB & MRI_Mod);
return !(MRB & Mod);
} }
/// onlyAccessesArgPointees - Return true if functions with the specified /// Checks if functions with the specified behavior are known to read and
/// behavior are known to read and write at most from objects pointed to by /// write at most from objects pointed to by their pointer-typed arguments
/// their pointer-typed arguments (with arbitrary offsets). /// (with arbitrary offsets).
/// static bool onlyAccessesArgPointees(FunctionModRefBehavior MRB) {
static bool onlyAccessesArgPointees(ModRefBehavior MRB) { return !(MRB & FMRL_Anywhere & ~FMRL_ArgumentPointees);
return !(MRB & Anywhere & ~ArgumentPointees);
} }
/// doesAccessArgPointees - Return true if functions with the specified /// Checks if functions with the specified behavior are known to potentially
/// behavior are known to potentially read or write from objects pointed /// read or write from objects pointed to be their pointer-typed arguments
/// to be their pointer-typed arguments (with arbitrary offsets). /// (with arbitrary offsets).
/// static bool doesAccessArgPointees(FunctionModRefBehavior MRB) {
static bool doesAccessArgPointees(ModRefBehavior MRB) { return (MRB & MRI_ModRef) && (MRB & FMRL_ArgumentPointees);
return (MRB & ModRef) && (MRB & ArgumentPointees);
} }
/// getModRefInfo - Return information about whether or not an /// getModRefInfo (for call sites) - Return information about whether
/// instruction may read or write memory (without regard to a /// a particular call site modifies or reads the specified memory location.
/// specific location) virtual ModRefInfo getModRefInfo(ImmutableCallSite CS,
ModRefResult getModRefInfo(const Instruction *I) { 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)) { if (auto CS = ImmutableCallSite(I)) {
auto MRB = getModRefBehavior(CS); auto MRB = getModRefBehavior(CS);
if (MRB & ModRef) if (MRB & MRI_ModRef)
return ModRef; return MRI_ModRef;
else if (MRB & Ref) else if (MRB & MRI_Ref)
return Ref; return MRI_Ref;
else if (MRB & Mod) else if (MRB & MRI_Mod)
return Mod; return MRI_Mod;
return NoModRef; return MRI_NoModRef;
} }
return getModRefInfo(I, Location()); return getModRefInfo(I, MemoryLocation());
} }
/// getModRefInfo - Return information about whether or not an instruction may /// Check whether or not an instruction may read or write the specified
/// read or write the specified memory location. An instruction /// memory location.
/// that doesn't read or write memory may be trivially LICM'd for example. ///
ModRefResult getModRefInfo(const Instruction *I, /// An instruction that doesn't read or write memory may be trivially LICM'd
const Location &Loc) { /// for example.
///
/// This primarily delegates to specific helpers above.
ModRefInfo getModRefInfo(const Instruction *I, const MemoryLocation &Loc) {
switch (I->getOpcode()) { switch (I->getOpcode()) {
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc); case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc);
case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc); case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc);
@ -343,201 +481,71 @@ public:
return getModRefInfo((const AtomicRMWInst*)I, Loc); return getModRefInfo((const AtomicRMWInst*)I, Loc);
case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc); case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc);
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc); case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
default: return NoModRef; default:
return MRI_NoModRef;
} }
} }
/// getModRefInfo - A convenience wrapper. /// A convenience wrapper for constructing the memory location.
ModRefResult getModRefInfo(const Instruction *I, ModRefInfo getModRefInfo(const Instruction *I, const Value *P,
const Value *P, uint64_t Size) { uint64_t Size) {
return getModRefInfo(I, Location(P, Size)); return getModRefInfo(I, MemoryLocation(P, Size));
} }
/// getModRefInfo (for call sites) - Return information about whether /// Return information about whether a call and an instruction may refer to
/// a particular call site modifies or reads the specified memory location. /// the same memory locations.
virtual ModRefResult getModRefInfo(ImmutableCallSite CS, ModRefInfo getModRefInfo(Instruction *I, ImmutableCallSite Call);
const Location &Loc);
/// getModRefInfo (for call sites) - A convenience wrapper. /// Return information about whether two call sites may refer to the same set
ModRefResult getModRefInfo(ImmutableCallSite CS, /// of memory locations. See the AA documentation for details:
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
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo /// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
/// for details. virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
ImmutableCallSite CS2); ImmutableCallSite CS2);
/// callCapturesBefore - Return information about whether a particular call /// \brief Return information about whether a particular call site modifies
/// site modifies or reads the specified memory location. /// or reads the specified memory location \p MemLoc before instruction \p I
ModRefResult callCapturesBefore(const Instruction *I, /// in a BasicBlock. A ordered basic block \p OBB can be used to speed up
const AliasAnalysis::Location &MemLoc, /// instruction ordering queries inside the BasicBlock containing \p I.
DominatorTree *DT); ModRefInfo callCapturesBefore(const Instruction *I,
const MemoryLocation &MemLoc, DominatorTree *DT,
OrderedBasicBlock *OBB = nullptr);
/// callCapturesBefore - A convenience wrapper. /// \brief A convenience wrapper to synthesize a memory location.
ModRefResult callCapturesBefore(const Instruction *I, const Value *P, ModRefInfo callCapturesBefore(const Instruction *I, const Value *P,
uint64_t Size, DominatorTree *DT) { uint64_t Size, DominatorTree *DT,
return callCapturesBefore(I, Location(P, Size), 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 /// Check if it is possible for execution of the specified basic block to
/// specified basic block to modify the location Loc. /// modify the location Loc.
bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc); bool canBasicBlockModify(const BasicBlock &BB, const MemoryLocation &Loc);
/// canBasicBlockModify - A convenience wrapper. /// A convenience wrapper synthesizing a memory location.
bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){ bool canBasicBlockModify(const BasicBlock &BB, const Value *P,
return canBasicBlockModify(BB, Location(P, Size)); uint64_t Size) {
return canBasicBlockModify(BB, MemoryLocation(P, Size));
} }
/// canInstructionRangeModRef - Return true if it is possible for the /// Check if it is possible for the execution of the specified instructions
/// execution of the specified instructions to mod\ref (according to the /// to mod\ref (according to the mode) the location Loc.
/// 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.
/// ///
/// 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 /// A convenience wrapper synthesizing a memory location.
/// deleted from the program, for example when an instruction is found to be bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2,
/// redundant and is eliminated. const Value *Ptr, uint64_t Size,
/// const ModRefInfo Mode) {
virtual void deleteValue(Value *V); return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode);
/// 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);
} }
}; };

View File

@ -117,24 +117,30 @@ class AliasSet : public ilist_node<AliasSet> {
// AliasSets forwarding to it. // AliasSets forwarding to it.
unsigned RefCount : 28; unsigned RefCount : 28;
/// AccessType - Keep track of whether this alias set merely refers to the /// The kinds of access this alias set models.
/// 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.
/// ///
enum AccessType { /// We keep track of whether this alias set merely refers to the locations of
NoModRef = 0, Refs = 1, // Ref = bit 1 /// memory (and not any particular access), whether it modifies or references
Mods = 2, ModRef = 3 // Mod = bit 2 /// 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. /// The kind of alias relationship between pointers of the set.
/// Lattice goes from MustAlias to MayAlias.
/// ///
enum AliasType { /// These represent conservatively correct alias results between any members
MustAlias = 0, MayAlias = 1 /// 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. // Volatile - True if this alias set contains volatile loads or stores.
bool Volatile : 1; bool Volatile : 1;
@ -153,10 +159,10 @@ class AliasSet : public ilist_node<AliasSet> {
public: public:
/// Accessors... /// Accessors...
bool isRef() const { return AccessTy & Refs; } bool isRef() const { return Access & RefAccess; }
bool isMod() const { return AccessTy & Mods; } bool isMod() const { return Access & ModAccess; }
bool isMustAlias() const { return AliasTy == MustAlias; } bool isMustAlias() const { return Alias == SetMustAlias; }
bool isMayAlias() const { return AliasTy == MayAlias; } bool isMayAlias() const { return Alias == SetMayAlias; }
// isVolatile - Return true if this alias set contains volatile loads or // isVolatile - Return true if this alias set contains volatile loads or
// stores. // stores.
@ -218,7 +224,7 @@ private:
friend struct ilist_sentinel_traits<AliasSet>; friend struct ilist_sentinel_traits<AliasSet>;
AliasSet() AliasSet()
: PtrList(nullptr), PtrListEnd(&PtrList), Forward(nullptr), RefCount(0), : 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; AliasSet(const AliasSet &AS) = delete;
@ -419,11 +425,11 @@ private:
} }
AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo, AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo,
AliasSet::AccessType E, AliasSet::AccessLattice E,
bool &NewSet) { bool &NewSet) {
NewSet = false; NewSet = false;
AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet); AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet);
AS.AccessTy |= E; AS.Access |= E;
return AS; return AS;
} }
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size, 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. /// \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. /// not already be in the cache.
void registerAssumption(CallInst *CI); void registerAssumption(CallInst *CI);
@ -79,7 +79,7 @@ public:
} }
/// \brief Access the list of assumption handles currently tracked for this /// \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 /// Note that these produce weak handles that may be null. The caller must
/// handle that case. /// handle that case.

View File

@ -21,26 +21,20 @@
namespace llvm { namespace llvm {
class BranchProbabilityInfo; class BranchProbabilityInfo;
class LoopInfo;
template <class BlockT> class BlockFrequencyInfoImpl; template <class BlockT> class BlockFrequencyInfoImpl;
/// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to /// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to
/// estimate IR basic block frequencies. /// estimate IR basic block frequencies.
class BlockFrequencyInfo : public FunctionPass { class BlockFrequencyInfo {
typedef BlockFrequencyInfoImpl<BasicBlock> ImplType; typedef BlockFrequencyInfoImpl<BasicBlock> ImplType;
std::unique_ptr<ImplType> BFI; std::unique_ptr<ImplType> BFI;
public: public:
static char ID;
BlockFrequencyInfo(); 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; const Function *getFunction() const;
void view() const; void view() const;
@ -51,6 +45,10 @@ public:
/// floating points. /// floating points.
BlockFrequency getBlockFreq(const BasicBlock *BB) const; 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 // Print the block frequency Freq to OS using the current functions entry
// frequency to convert freq into a relative decimal form. // frequency to convert freq into a relative decimal form.
raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const; 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; raw_ostream &printBlockFreq(raw_ostream &OS, const BasicBlock *BB) const;
uint64_t getEntryFreq() 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 { struct LoopData {
typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap; typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap;
typedef SmallVector<BlockNode, 4> NodeList; typedef SmallVector<BlockNode, 4> NodeList;
typedef SmallVector<BlockMass, 1> HeaderMassList;
LoopData *Parent; ///< The parent loop. LoopData *Parent; ///< The parent loop.
bool IsPackaged; ///< Whether this has been packaged. bool IsPackaged; ///< Whether this has been packaged.
uint32_t NumHeaders; ///< Number of headers. uint32_t NumHeaders; ///< Number of headers.
ExitMap Exits; ///< Successor edges (and weights). ExitMap Exits; ///< Successor edges (and weights).
NodeList Nodes; ///< Header and the members of the loop. NodeList Nodes; ///< Header and the members of the loop.
BlockMass BackedgeMass; ///< Mass returned to loop header. HeaderMassList BackedgeMass; ///< Mass returned to each loop header.
BlockMass Mass; BlockMass Mass;
Scaled64 Scale; Scaled64 Scale;
LoopData(LoopData *Parent, const BlockNode &Header) 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> template <class It1, class It2>
LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther, LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther,
It2 LastOther) It2 LastOther)
: Parent(Parent), IsPackaged(false), Nodes(FirstHeader, LastHeader) { : Parent(Parent), IsPackaged(false), Nodes(FirstHeader, LastHeader) {
NumHeaders = Nodes.size(); NumHeaders = Nodes.size();
Nodes.insert(Nodes.end(), FirstOther, LastOther); Nodes.insert(Nodes.end(), FirstOther, LastOther);
BackedgeMass.resize(NumHeaders);
} }
bool isHeader(const BlockNode &Node) const { bool isHeader(const BlockNode &Node) const {
if (isIrreducible()) if (isIrreducible())
@ -223,6 +226,14 @@ public:
BlockNode getHeader() const { return Nodes[0]; } BlockNode getHeader() const { return Nodes[0]; }
bool isIrreducible() const { return NumHeaders > 1; } 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 { NodeList::const_iterator members_begin() const {
return Nodes.begin() + NumHeaders; return Nodes.begin() + NumHeaders;
} }
@ -431,6 +442,16 @@ public:
/// \brief Compute the loop scale for a loop. /// \brief Compute the loop scale for a loop.
void computeLoopScale(LoopData &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. /// \brief Package up a loop.
void packageLoop(LoopData &Loop); void packageLoop(LoopData &Loop);
@ -695,6 +716,17 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
/// - Distribute the mass accordingly, dithering to minimize mass loss, /// - Distribute the mass accordingly, dithering to minimize mass loss,
/// as described in \a distributeMass(). /// 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. /// Finally, calculate the loop scale from the accumulated backedge mass.
/// ///
/// 3. Distribute mass in the function (\a computeMassInFunction()). /// 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 /// as sub-loops, rather than arbitrarily shoving the problematic
/// blocks into the headers of the main irreducible SCC. /// 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 /// - Entry frequencies are assumed to be evenly split between the
/// headers of a given irreducible SCC, which is the only option if we /// 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, /// 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 /// \pre \a computeMassInLoop() has been called for each subloop of \c
/// OuterLoop. /// 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(). /// computeMassInLoop().
/// \pre \c OuterLoop has irreducible SCCs. /// \pre \c OuterLoop has irreducible SCCs.
void computeIrreducibleMass(LoopData *OuterLoop, void computeIrreducibleMass(LoopData *OuterLoop,
@ -878,8 +905,8 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
public: public:
const FunctionT *getFunction() const { return F; } const FunctionT *getFunction() const { return F; }
void doFunction(const FunctionT *F, const BranchProbabilityInfoT *BPI, void calculate(const FunctionT &F, const BranchProbabilityInfoT &BPI,
const LoopInfoT *LI); const LoopInfoT &LI);
BlockFrequencyInfoImpl() : BPI(nullptr), LI(nullptr), F(nullptr) {} BlockFrequencyInfoImpl() : BPI(nullptr), LI(nullptr), F(nullptr) {}
using BlockFrequencyInfoImplBase::getEntryFreq; using BlockFrequencyInfoImplBase::getEntryFreq;
@ -911,13 +938,13 @@ public:
}; };
template <class BT> template <class BT>
void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F, void BlockFrequencyInfoImpl<BT>::calculate(const FunctionT &F,
const BranchProbabilityInfoT *BPI, const BranchProbabilityInfoT &BPI,
const LoopInfoT *LI) { const LoopInfoT &LI) {
// Save the parameters. // Save the parameters.
this->BPI = BPI; this->BPI = &BPI;
this->LI = LI; this->LI = &LI;
this->F = F; this->F = &F;
// Clean up left-over data structures. // Clean up left-over data structures.
BlockFrequencyInfoImplBase::clear(); BlockFrequencyInfoImplBase::clear();
@ -925,8 +952,8 @@ void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
Nodes.clear(); Nodes.clear();
// Initialize. // Initialize.
DEBUG(dbgs() << "\nblock-frequency: " << F->getName() << "\n=================" DEBUG(dbgs() << "\nblock-frequency: " << F.getName() << "\n================="
<< std::string(F->getName().size(), '=') << "\n"); << std::string(F.getName().size(), '=') << "\n");
initializeRPOT(); initializeRPOT();
initializeLoops(); initializeLoops();
@ -1042,6 +1069,8 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
for (const BlockNode &M : Loop.Nodes) for (const BlockNode &M : Loop.Nodes)
if (!propagateMassToSuccessors(&Loop, M)) if (!propagateMassToSuccessors(&Loop, M))
llvm_unreachable("unhandled irreducible control flow"); llvm_unreachable("unhandled irreducible control flow");
adjustLoopHeaderMass(Loop);
} else { } else {
Working[Loop.getHeader().Index].getMass() = BlockMass::getFull(); Working[Loop.getHeader().Index].getMass() = BlockMass::getFull();
if (!propagateMassToSuccessors(&Loop, Loop.getHeader())) if (!propagateMassToSuccessors(&Loop, Loop.getHeader()))

View File

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

View File

@ -78,6 +78,17 @@ bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To,
const DominatorTree *DT = nullptr, const DominatorTree *DT = nullptr,
const LoopInfo *LI = 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 } // End llvm namespace
#endif #endif

View File

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

View File

@ -20,6 +20,7 @@ namespace llvm {
class Use; class Use;
class Instruction; class Instruction;
class DominatorTree; class DominatorTree;
class OrderedBasicBlock;
/// PointerMayBeCaptured - Return true if this pointer value may be captured /// PointerMayBeCaptured - Return true if this pointer value may be captured
/// by the enclosing function (which is required to exist). This routine can /// 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 /// it or not. The boolean StoreCaptures specified whether storing the value
/// (or part of it) into memory anywhere automatically counts as capturing it /// (or part of it) into memory anywhere automatically counts as capturing it
/// or not. Captures by the provided instruction are considered if the /// 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 PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
bool StoreCaptures, const Instruction *I, 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 /// This callback is used in conjunction with PointerMayBeCaptured. In
/// addition to the interface here, you'll need to provide your own getters /// 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, Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
ArrayRef<unsigned> Idxs); 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 /// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
/// produce if it is constant and determinable. If this is not determinable, /// produce if it is constant and determinable. If this is not determinable,
/// return null. /// return null.

View File

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

View File

@ -21,6 +21,7 @@
namespace llvm { namespace llvm {
class AssumptionCache;
class DominatorTree; class DominatorTree;
class Instruction; class Instruction;
class Value; class Value;
@ -119,15 +120,19 @@ private:
class IVUsers : public LoopPass { class IVUsers : public LoopPass {
friend class IVStrideUse; friend class IVStrideUse;
Loop *L; Loop *L;
AssumptionCache *AC;
LoopInfo *LI; LoopInfo *LI;
DominatorTree *DT; DominatorTree *DT;
ScalarEvolution *SE; ScalarEvolution *SE;
SmallPtrSet<Instruction*,16> Processed; SmallPtrSet<Instruction*, 16> Processed;
/// IVUses - A list of all tracked IV uses of induction variable expressions /// IVUses - A list of all tracked IV uses of induction variable expressions
/// we are interested in. /// we are interested in.
ilist<IVStrideUse> IVUses; ilist<IVStrideUse> IVUses;
// Ephemeral values used by @llvm.assume in this function.
SmallPtrSet<const Value *, 32> EphValues;
void getAnalysisUsage(AnalysisUsage &AU) const override; void getAnalysisUsage(AnalysisUsage &AU) const override;
bool runOnLoop(Loop *L, LPPassManager &LPM) 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 /// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
/// fold the result. If not, this returns null. /// fold the result. If not, this returns null.
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS, Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
const DataLayout &DL, FastMathFlags FMF, const DataLayout &DL,
const TargetLibraryInfo *TLI = nullptr, const TargetLibraryInfo *TLI = nullptr,
const DominatorTree *DT = nullptr, const DominatorTree *DT = nullptr,
AssumptionCache *AC = nullptr, AssumptionCache *AC = nullptr,
@ -244,6 +244,24 @@ namespace llvm {
AssumptionCache *AC = nullptr, AssumptionCache *AC = nullptr,
const Instruction *CxtI = 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 /// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
/// the result. If not, this returns null. /// the result. If not, this returns null.
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL, 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 { Function &getFunction() const {
return F; return F;
}; }
iterator begin() const { iterator begin() const {
return iterator(*G, Callees.begin(), Callees.end()); return iterator(*G, Callees.begin(), Callees.end());

View File

@ -46,7 +46,6 @@ public:
Unknown = -1, False = 0, True = 1 Unknown = -1, False = 0, True = 1
}; };
// Public query interface. // Public query interface.
/// Determine whether the specified value comparison with a constant is known /// Determine whether the specified value comparison with a constant is known

View File

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

View File

@ -48,8 +48,7 @@ class InvokeInst;
enum LocResult { enum LocResult {
Yes, No, Unknown Yes, No, Unknown
}; };
LocResult (*isLocation)(ImmutableCallSite CS, LocResult (*isLocation)(ImmutableCallSite CS, const MemoryLocation &Loc);
const AliasAnalysis::Location &Loc);
}; };
/// LibCallFunctionInfo - Each record in the array of FunctionInfo structs /// LibCallFunctionInfo - Each record in the array of FunctionInfo structs
@ -72,7 +71,7 @@ class InvokeInst;
/// any specific context knowledge. For example, if the function is known /// 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, /// to be readonly, this would be set to 'ref'. If known to be readnone,
/// this is set to NoModRef. /// this is set to NoModRef.
AliasAnalysis::ModRefResult UniversalBehavior; ModRefInfo UniversalBehavior;
/// LocationMRInfo - This pair captures info about whether a specific /// LocationMRInfo - This pair captures info about whether a specific
/// location is modified or referenced by a libcall. /// location is modified or referenced by a libcall.
@ -80,7 +79,7 @@ class InvokeInst;
/// LocationID - ID # of the accessed location or ~0U for array end. /// LocationID - ID # of the accessed location or ~0U for array end.
unsigned LocationID; unsigned LocationID;
/// MRInfo - Mod/Ref info for this location. /// MRInfo - Mod/Ref info for this location.
AliasAnalysis::ModRefResult MRInfo; ModRefInfo MRInfo;
}; };
/// DetailsType - Indicate the sense of the LocationDetails array. This /// DetailsType - Indicate the sense of the LocationDetails array. This
@ -207,7 +206,19 @@ class InvokeInst;
llvm_unreachable("invalid enum"); 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 } // end namespace llvm

View File

@ -292,53 +292,110 @@ private:
bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize); bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize);
}; };
/// \brief Drive the analysis of memory accesses in the loop /// \brief Holds information about the memory runtime legality checks to verify
/// /// that a group of pointers do not overlap.
/// This class is responsible for analyzing the memory accesses of a loop. It class RuntimePointerChecking {
/// collects the accesses and then its main helper the AccessAnalysis class
/// finds and categorizes the dependences in buildDependenceSets.
///
/// For memory dependences that can be analyzed at compile time, it determines
/// whether the dependence is part of cycle inhibiting vectorization. This work
/// is delegated to the MemoryDepChecker class.
///
/// For memory dependences that cannot be determined at compile time, it
/// generates run-time checks to prove independence. This is done by
/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the
/// RuntimePointerCheck class.
class LoopAccessInfo {
public: public:
/// This struct holds information about the memory runtime legality check that struct PointerInfo {
/// a group of pointers do not overlap. /// Holds the pointer value that we need to check.
struct RuntimePointerCheck { TrackingVH<Value> PointerValue;
RuntimePointerCheck() : Need(false) {} /// 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. /// Reset the state of the pointer runtime information.
void reset() { void reset() {
Need = false; Need = false;
Pointers.clear(); Pointers.clear();
Starts.clear();
Ends.clear();
IsWritePtr.clear();
DependencySetId.clear();
AliasSetId.clear();
} }
/// Insert a pointer and calculate the start and end SCEVs. /// Insert a pointer and calculate the start and end SCEVs.
void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr, void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,
unsigned DepSetId, unsigned ASId, unsigned ASId, const ValueToValueMap &Strides);
const ValueToValueMap &Strides);
/// \brief No run-time memory checking is necessary. /// \brief No run-time memory checking is necessary.
bool empty() const { return Pointers.empty(); } bool empty() const { return Pointers.empty(); }
/// \brief Decide whether we need to issue a run-time check for pointer at /// A grouping of pointers. A single memcheck is required between
/// index \p I and \p J to prove their independence. /// 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.
/// ///
/// If \p PtrPartition is set, it contains the partition number for /// These *have* to be const for now, since checks are generated from
/// pointers (-1 if the pointer belongs to multiple partitions). In this /// CheckingPtrGroups in LAI::addRuntimeCheck which is a const member
/// case omit checks between pointers belonging to the same partition. /// function. FIXME: once check-generation is moved inside this class (after
bool needsChecking(unsigned I, unsigned J, /// 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; const SmallVectorImpl<int> *PtrPartition) const;
/// \brief Return true if any pointer requires run-time checking according /// \brief Return true if any pointer requires run-time checking according
@ -357,23 +414,57 @@ public:
void print(raw_ostream &OS, unsigned Depth = 0, void print(raw_ostream &OS, unsigned Depth = 0,
const SmallVectorImpl<int> *PtrPartition = nullptr) const; 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. /// This flag indicates if we need to add the runtime check.
bool Need; 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;
};
/// 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
/// collects the accesses and then its main helper the AccessAnalysis class
/// finds and categorizes the dependences in buildDependenceSets.
///
/// For memory dependences that can be analyzed at compile time, it determines
/// whether the dependence is part of cycle inhibiting vectorization. This work
/// is delegated to the MemoryDepChecker class.
///
/// For memory dependences that cannot be determined at compile time, it
/// generates run-time checks to prove independence. This is done by
/// AccessAnalysis::canCheckPtrAtRT and the checks are maintained by the
/// RuntimePointerCheck class.
class LoopAccessInfo {
public:
LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL, LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,
const TargetLibraryInfo *TLI, AliasAnalysis *AA, const TargetLibraryInfo *TLI, AliasAnalysis *AA,
DominatorTree *DT, LoopInfo *LI, DominatorTree *DT, LoopInfo *LI,
@ -383,15 +474,15 @@ public:
/// no memory dependence cycles. /// no memory dependence cycles.
bool canVectorizeMemory() const { return CanVecMem; } bool canVectorizeMemory() const { return CanVecMem; }
const RuntimePointerCheck *getRuntimePointerCheck() const { const RuntimePointerChecking *getRuntimePointerChecking() const {
return &PtrRtCheck; return &PtrRtChecking;
} }
/// \brief Number of memchecks required to prove independence of otherwise /// \brief Number of memchecks required to prove independence of otherwise
/// may-alias pointers. /// may-alias pointers.
unsigned getNumRuntimePointerChecks( unsigned getNumRuntimePointerChecks(
const SmallVectorImpl<int> *PtrPartition = nullptr) const { 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 /// Return true if the block BB needs to be predicated in order for the loop
@ -419,6 +510,16 @@ public:
addRuntimeCheck(Instruction *Loc, addRuntimeCheck(Instruction *Loc,
const SmallVectorImpl<int> *PtrPartition = nullptr) const; 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 /// \brief The diagnostics report generated for the analysis. E.g. why we
/// couldn't analyze the loop. /// couldn't analyze the loop.
const Optional<LoopAccessReport> &getReport() const { return Report; } 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 /// We need to check that all of the pointers in this list are disjoint
/// at runtime. /// at runtime.
RuntimePointerCheck PtrRtCheck; RuntimePointerChecking PtrRtChecking;
/// \brief the Memory Dependence Checker which can determine the /// \brief the Memory Dependence Checker which can determine the
/// loop-independent and loop-carried dependences between memory accesses. /// 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 // Implementation in LoopInfoImpl.h
#ifdef __GNUC__ extern template class LoopBase<BasicBlock, Loop>;
__extension__ extern template class LoopBase<BasicBlock, Loop>;
#endif
class Loop : public LoopBase<BasicBlock, Loop> { class Loop : public LoopBase<BasicBlock, Loop> {
public: public:
@ -624,7 +622,7 @@ public:
} }
/// Create the loop forest using a stable algorithm. /// Create the loop forest using a stable algorithm.
void Analyze(DominatorTreeBase<BlockT> &DomTree); void analyze(const DominatorTreeBase<BlockT> &DomTree);
// Debugging // Debugging
void print(raw_ostream &OS) const; void print(raw_ostream &OS) const;
@ -633,9 +631,7 @@ public:
}; };
// Implementation in LoopInfoImpl.h // Implementation in LoopInfoImpl.h
#ifdef __GNUC__ extern template class LoopInfoBase<BasicBlock, Loop>;
__extension__ extern template class LoopInfoBase<BasicBlock, Loop>;
#endif
class LoopInfo : public LoopInfoBase<BasicBlock, Loop> { class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
typedef LoopInfoBase<BasicBlock, Loop> BaseT; typedef LoopInfoBase<BasicBlock, Loop> BaseT;
@ -646,6 +642,7 @@ class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
LoopInfo(const LoopInfo &) = delete; LoopInfo(const LoopInfo &) = delete;
public: public:
LoopInfo() {} LoopInfo() {}
explicit LoopInfo(const DominatorTreeBase<BasicBlock> &DomTree);
LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {} LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
LoopInfo &operator=(LoopInfo &&RHS) { 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> template<class BlockT, class LoopT>
static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges, static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
LoopInfoBase<BlockT, LoopT> *LI, LoopInfoBase<BlockT, LoopT> *LI,
DominatorTreeBase<BlockT> &DomTree) { const DominatorTreeBase<BlockT> &DomTree) {
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits; typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
unsigned NumBlocks = 0; unsigned NumBlocks = 0;
@ -468,10 +468,10 @@ void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) {
/// insertions per block. /// insertions per block.
template<class BlockT, class LoopT> template<class BlockT, class LoopT>
void LoopInfoBase<BlockT, LoopT>:: void LoopInfoBase<BlockT, LoopT>::
Analyze(DominatorTreeBase<BlockT> &DomTree) { analyze(const DominatorTreeBase<BlockT> &DomTree) {
// Postorder traversal of the dominator tree. // Postorder traversal of the dominator tree.
DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode(); const DomTreeNodeBase<BlockT> *DomRoot = DomTree.getRootNode();
for (auto DomNode : post_order(DomRoot)) { for (auto DomNode : post_order(DomRoot)) {
BlockT *Header = DomNode->getBlock(); BlockT *Header = DomNode->getBlock();

View File

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

View File

@ -26,6 +26,7 @@ class LoadInst;
class StoreInst; class StoreInst;
class MemTransferInst; class MemTransferInst;
class MemIntrinsic; class MemIntrinsic;
class TargetLibraryInfo;
/// Representation for a specific memory location. /// Representation for a specific memory location.
/// ///
@ -87,6 +88,10 @@ public:
/// transfer. /// transfer.
static MemoryLocation getForDest(const MemIntrinsic *MI); 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, explicit MemoryLocation(const Value *Ptr = nullptr,
uint64_t Size = UnknownSize, uint64_t Size = UnknownSize,
const AAMDNodes &AATags = AAMDNodes()) 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(); return OS << Node.template getNodeAs<BlockT>()->getName();
} }
EXTERN_TEMPLATE_INSTANTIATION(class RegionBase<RegionTraits<Function>>); extern template class RegionBase<RegionTraits<Function>>;
EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase<RegionTraits<Function>>); extern template class RegionNodeBase<RegionTraits<Function>>;
EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase<RegionTraits<Function>>); extern template class RegionInfoBase<RegionTraits<Function>>;
} // End llvm namespace } // End llvm namespace
#endif #endif

View File

@ -48,6 +48,7 @@ namespace llvm {
class LoopInfo; class LoopInfo;
class Operator; class Operator;
class SCEVUnknown; class SCEVUnknown;
class SCEVAddRecExpr;
class SCEV; class SCEV;
template<> struct FoldingSetTrait<SCEV>; template<> struct FoldingSetTrait<SCEV>;
@ -565,19 +566,43 @@ namespace llvm {
/// forgetMemoizedResults - Drop memoized information computed for S. /// forgetMemoizedResults - Drop memoized information computed for S.
void forgetMemoizedResults(const SCEV *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- /// Return false iff given SCEV contains a SCEVUnknown with NULL value-
/// pointer. /// pointer.
bool checkValidity(const SCEV *S) const; bool checkValidity(const SCEV *S) const;
// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be equal /// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be
// to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is equivalent to /// equal to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is
// proving no signed (resp. unsigned) wrap in {`Start`,+,`Step`} if /// equivalent to proving no signed (resp. unsigned) wrap in
// `ExtendOpTy` is `SCEVSignExtendExpr` (resp. `SCEVZeroExtendExpr`). /// {`Start`,+,`Step`} if `ExtendOpTy` is `SCEVSignExtendExpr`
// /// (resp. `SCEVZeroExtendExpr`).
///
template<typename ExtendOpTy> template<typename ExtendOpTy>
bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step, bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
const Loop *L); 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: public:
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
ScalarEvolution(); ScalarEvolution();
@ -899,6 +924,16 @@ namespace llvm {
bool isKnownPredicate(ICmpInst::Predicate Pred, bool isKnownPredicate(ICmpInst::Predicate Pred,
const SCEV *LHS, const SCEV *RHS); 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 /// SimplifyICmpOperands - Simplify LHS and RHS in a comparison with
/// predicate Pred. Return true iff any changes were made. If the /// predicate Pred. Return true iff any changes were made. If the
/// operands are provably equal or unequal, LHS and RHS are set to /// 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 print(raw_ostream &OS, const Module* = nullptr) const override;
void verifyAnalysis() 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: private:
/// Compute the backedge taken count knowing the interval difference, the /// Compute the backedge taken count knowing the interval difference, the
/// stride and presence of the equality in the comparison. /// stride and presence of the equality in the comparison.

View File

@ -356,84 +356,6 @@ namespace llvm {
static inline bool classof(const SCEV *S) { static inline bool classof(const SCEV *S) {
return S->getSCEVType() == scAddRecExpr; 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