mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-09 01:38:03 +00:00
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:
commit
d33a944a7d
2
.gitignore
vendored
2
.gitignore
vendored
@ -44,7 +44,7 @@ autoconf/autom4te.cache
|
||||
#==============================================================================#
|
||||
# External projects that are tracked independently.
|
||||
projects/*
|
||||
!projects/CMakeLists.txt
|
||||
!projects/*.*
|
||||
!projects/Makefile
|
||||
# Clang, which is tracked independently.
|
||||
tools/clang
|
||||
|
@ -26,7 +26,7 @@ else()
|
||||
set(cmake_3_2_USES_TERMINAL USES_TERMINAL)
|
||||
endif()
|
||||
|
||||
project(LLVM)
|
||||
project(LLVM C CXX ASM)
|
||||
|
||||
# The following only works with the Ninja generator in CMake >= 3.0.
|
||||
set(LLVM_PARALLEL_COMPILE_JOBS "" CACHE STRING
|
||||
@ -59,7 +59,7 @@ set(CMAKE_MODULE_PATH
|
||||
)
|
||||
|
||||
set(LLVM_VERSION_MAJOR 3)
|
||||
set(LLVM_VERSION_MINOR 7)
|
||||
set(LLVM_VERSION_MINOR 8)
|
||||
set(LLVM_VERSION_PATCH 0)
|
||||
set(LLVM_VERSION_SUFFIX svn)
|
||||
|
||||
@ -530,7 +530,7 @@ endif()
|
||||
# check its symbols. This is wasteful (the check was done when foo.so
|
||||
# was created) and can fail since it is not the dynamic linker and
|
||||
# doesn't know how to handle search paths correctly.
|
||||
if (UNIX AND NOT APPLE)
|
||||
if (UNIX AND NOT APPLE AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -Wl,-allow-shlib-undefined")
|
||||
endif()
|
||||
|
@ -65,6 +65,10 @@ N: Hal Finkel
|
||||
E: hfinkel@anl.gov
|
||||
D: BBVectorize, the loop reroller, alias analysis and the PowerPC target
|
||||
|
||||
N: Dan Gohman
|
||||
E: sunfish@mozilla.com
|
||||
D: WebAssembly Backend (lib/Target/WebAssembly/*)
|
||||
|
||||
N: Renato Golin
|
||||
E: renato.golin@linaro.org
|
||||
D: ARM Linux support
|
||||
|
@ -152,8 +152,9 @@ E: foldr@codedgers.com
|
||||
D: Author of llvmc2
|
||||
|
||||
N: Dan Gohman
|
||||
E: dan433584@gmail.com
|
||||
E: sunfish@mozilla.com
|
||||
D: Miscellaneous bug fixes
|
||||
D: WebAssembly Backend
|
||||
|
||||
N: David Goodwin
|
||||
E: david@goodwinz.net
|
||||
|
@ -58,20 +58,9 @@ LLVM_OBJ_ROOT := $(call realpath, @abs_top_builddir@)
|
||||
PROJ_SRC_ROOT := $(LLVM_SRC_ROOT)
|
||||
PROJ_SRC_DIR := $(LLVM_SRC_ROOT)$(patsubst $(PROJ_OBJ_ROOT)%,%,$(PROJ_OBJ_DIR))
|
||||
|
||||
# FIXME: This is temporary during the grace period where in-source builds are
|
||||
# deprecated. Convert to a hard error when that period is up.
|
||||
#
|
||||
# See: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20150323/268067.html
|
||||
ifeq ($(LLVM_SRC_ROOT), $(LLVM_OBJ_ROOT))
|
||||
$(warning ######################################################################################)
|
||||
$(warning # #)
|
||||
$(warning # WARNING #)
|
||||
$(warning # #)
|
||||
$(warning # In-source builds are deprecated. #)
|
||||
$(warning # #)
|
||||
$(warning # Please configure from a separate build directory! #)
|
||||
$(warning # #)
|
||||
$(warning ######################################################################################)
|
||||
$(error In-source builds are not allowed. Please configure from a separate build directory!)
|
||||
endif
|
||||
|
||||
ifneq ($(CLANG_SRC_ROOT),)
|
||||
|
3
autoconf/config.guess
vendored
3
autoconf/config.guess
vendored
@ -810,6 +810,9 @@ EOF
|
||||
*:MINGW*:*)
|
||||
echo ${UNAME_MACHINE}-pc-mingw32
|
||||
exit ;;
|
||||
*:MSYS*:*)
|
||||
echo ${UNAME_MACHINE}-pc-msys
|
||||
exit ;;
|
||||
i*:windows32*:*)
|
||||
# uname -m includes "-pc" on this system.
|
||||
echo ${UNAME_MACHINE}-mingw32
|
||||
|
@ -32,10 +32,10 @@ dnl===-----------------------------------------------------------------------===
|
||||
dnl Initialize autoconf and define the package name, version number and
|
||||
dnl address for reporting bugs.
|
||||
|
||||
AC_INIT([LLVM],[3.7.0svn],[http://llvm.org/bugs/])
|
||||
AC_INIT([LLVM],[3.8.0svn],[http://llvm.org/bugs/])
|
||||
|
||||
LLVM_VERSION_MAJOR=3
|
||||
LLVM_VERSION_MINOR=7
|
||||
LLVM_VERSION_MINOR=8
|
||||
LLVM_VERSION_PATCH=0
|
||||
LLVM_VERSION_SUFFIX=svn
|
||||
|
||||
@ -75,15 +75,7 @@ fi
|
||||
|
||||
dnl Quit if it is an in-source build
|
||||
if test ${srcdir} == "." ; then
|
||||
AC_MSG_WARN([**************************************************************************************])
|
||||
AC_MSG_WARN([* *])
|
||||
AC_MSG_WARN([* WARNING *])
|
||||
AC_MSG_WARN([* *])
|
||||
AC_MSG_WARN([* In-source builds are deprecated. *])
|
||||
AC_MSG_WARN([* *])
|
||||
AC_MSG_WARN([* Please configure from a separate build directory! *])
|
||||
AC_MSG_WARN([* *])
|
||||
AC_MSG_WARN([**************************************************************************************])
|
||||
AC_MSG_ERROR([In-source builds are not allowed. Please configure from a separate build directory!])
|
||||
fi
|
||||
|
||||
dnl Default to empty (i.e. assigning the null string to) CFLAGS and CXXFLAGS,
|
||||
@ -445,6 +437,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch],
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
nvptx-*) llvm_cv_target_arch="NVPTX" ;;
|
||||
s390x-*) llvm_cv_target_arch="SystemZ" ;;
|
||||
wasm*-*) llvm_cv_target_arch="WebAssembly" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
esac])
|
||||
|
||||
@ -480,6 +473,7 @@ case $host in
|
||||
msp430-*) host_arch="MSP430" ;;
|
||||
hexagon-*) host_arch="Hexagon" ;;
|
||||
s390x-*) host_arch="SystemZ" ;;
|
||||
wasm*-*) host_arch="WebAssembly" ;;
|
||||
*) host_arch="Unknown" ;;
|
||||
esac
|
||||
|
||||
@ -812,6 +806,7 @@ else
|
||||
Hexagon) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
NVPTX) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
SystemZ) AC_SUBST(TARGET_HAS_JIT,1) ;;
|
||||
WebAssembly) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
*) AC_SUBST(TARGET_HAS_JIT,0) ;;
|
||||
esac
|
||||
fi
|
||||
@ -1105,7 +1100,7 @@ TARGETS_TO_BUILD=""
|
||||
AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets],
|
||||
[Build specific host targets: all or target1,target2,... Valid targets are:
|
||||
host, x86, x86_64, sparc, powerpc, arm64, arm, aarch64, mips, hexagon,
|
||||
xcore, msp430, nvptx, systemz, r600, bpf, and cpp (default=all)]),,
|
||||
xcore, msp430, nvptx, systemz, r600, bpf, wasm, and cpp (default=all)]),,
|
||||
enableval=all)
|
||||
if test "$enableval" = host-only ; then
|
||||
enableval=host
|
||||
@ -1134,6 +1129,7 @@ case "$enableval" in
|
||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
|
||||
wasm) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;;
|
||||
host) case "$llvm_cv_target_arch" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -1147,6 +1143,7 @@ case "$enableval" in
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
|
||||
SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
WebAssembly) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;;
|
||||
*) AC_MSG_ERROR([Can not set target to build]) ;;
|
||||
esac ;;
|
||||
*) AC_MSG_ERROR([Unrecognized target $a_target]) ;;
|
||||
@ -1631,7 +1628,7 @@ dnl===-----------------------------------------------------------------------===
|
||||
|
||||
AC_CHECK_LIB(m,sin)
|
||||
if test "$llvm_cv_os_type" = "MingW" ; then
|
||||
AC_CHECK_LIB(imagehlp, main)
|
||||
AC_CHECK_LIB(ole32, main)
|
||||
AC_CHECK_LIB(psapi, main)
|
||||
AC_CHECK_LIB(shell32, main)
|
||||
fi
|
||||
@ -2172,7 +2169,10 @@ dnl contains the same list of files as AC_CONFIG_HEADERS below. This ensures the
|
||||
dnl files can be updated automatically when their *.in sources change.
|
||||
AC_CONFIG_HEADERS([include/llvm/Config/config.h include/llvm/Config/llvm-config.h])
|
||||
AH_TOP([#ifndef CONFIG_H
|
||||
#define CONFIG_H])
|
||||
#define CONFIG_H
|
||||
|
||||
/* Exported configuration */
|
||||
#include "llvm/Config/llvm-config.h"])
|
||||
AH_BOTTOM([#endif])
|
||||
|
||||
AC_CONFIG_FILES([include/llvm/Config/Targets.def])
|
||||
|
@ -84,13 +84,18 @@ LLVMMetadataRef LLVMDIBuilderCreateFunction(
|
||||
}
|
||||
|
||||
LLVMMetadataRef LLVMDIBuilderCreateLocalVariable(
|
||||
LLVMDIBuilderRef Dref, unsigned Tag, LLVMMetadataRef Scope,
|
||||
LLVMDIBuilderRef Dref, unsigned, LLVMMetadataRef Scope,
|
||||
const char *Name, LLVMMetadataRef File, unsigned Line, LLVMMetadataRef Ty,
|
||||
int AlwaysPreserve, unsigned Flags, unsigned ArgNo) {
|
||||
DIBuilder *D = unwrap(Dref);
|
||||
return wrap(D->createLocalVariable(
|
||||
Tag, unwrap<DIScope>(Scope), Name, unwrap<DIFile>(File), Line,
|
||||
unwrap<DIType>(Ty), AlwaysPreserve, Flags, ArgNo));
|
||||
// FIXME: Update the Go bindings to match the DIBuilder API.
|
||||
if (ArgNo)
|
||||
return wrap(D->createParameterVariable(
|
||||
unwrap<DIScope>(Scope), Name, ArgNo, unwrap<DIFile>(File), Line,
|
||||
unwrap<DIType>(Ty), AlwaysPreserve, Flags));
|
||||
return wrap(D->createAutoVariable(unwrap<DIScope>(Scope), Name,
|
||||
unwrap<DIFile>(File), Line,
|
||||
unwrap<DIType>(Ty), AlwaysPreserve, Flags));
|
||||
}
|
||||
|
||||
LLVMMetadataRef LLVMDIBuilderCreateBasicType(LLVMDIBuilderRef Dref,
|
||||
|
@ -160,6 +160,8 @@ const (
|
||||
InAllocaAttribute Attribute = 1 << 43
|
||||
NonNullAttribute Attribute = 1 << 44
|
||||
JumpTableAttribute Attribute = 1 << 45
|
||||
ConvergentAttribute Attribute = 1 << 46
|
||||
SafeStackAttribute Attribute = 1 << 47
|
||||
)
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
@ -1052,6 +1054,9 @@ func (v Value) AddTargetDependentFunctionAttr(attr, value string) {
|
||||
defer C.free(unsafe.Pointer(cvalue))
|
||||
C.LLVMAddTargetDependentFunctionAttr(v.C, cattr, cvalue)
|
||||
}
|
||||
func (v Value) SetPersonality(p Value) {
|
||||
C.LLVMSetPersonalityFn(v.C, p.C)
|
||||
}
|
||||
|
||||
// Operations on parameters
|
||||
func (v Value) ParamsCount() int { return int(C.LLVMCountParams(v.C)) }
|
||||
@ -1204,7 +1209,7 @@ func (b Builder) Dispose() { C.LLVMDisposeBuilder(b.C) }
|
||||
func (b Builder) SetCurrentDebugLocation(line, col uint, scope, inlinedAt Metadata) {
|
||||
C.LLVMSetCurrentDebugLocation2(b.C, C.unsigned(line), C.unsigned(col), scope.C, inlinedAt.C)
|
||||
}
|
||||
func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) }
|
||||
func (b Builder) SetInstDebugLocation(v Value) { C.LLVMSetInstDebugLocation(b.C, v.C) }
|
||||
func (b Builder) InsertDeclare(module Module, storage Value, md Value) Value {
|
||||
f := module.NamedFunction("llvm.dbg.declare")
|
||||
if f.IsNil() {
|
||||
@ -1723,10 +1728,10 @@ func (b Builder) CreatePtrDiff(lhs, rhs Value, name string) (v Value) {
|
||||
return
|
||||
}
|
||||
|
||||
func (b Builder) CreateLandingPad(t Type, personality Value, nclauses int, name string) (l Value) {
|
||||
func (b Builder) CreateLandingPad(t Type, nclauses int, name string) (l Value) {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
l.C = C.LLVMBuildLandingPad(b.C, t.C, personality.C, C.unsigned(nclauses), cname)
|
||||
l.C = C.LLVMBuildLandingPad(b.C, t.C, nil, C.unsigned(nclauses), cname)
|
||||
return l
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,7 @@ func TestAttributes(t *testing.T) {
|
||||
{AlwaysInlineAttribute, "alwaysinline"},
|
||||
{BuiltinAttribute, "builtin"},
|
||||
{ByValAttribute, "byval"},
|
||||
{ConvergentAttribute, "convergent"},
|
||||
{InAllocaAttribute, "inalloca"},
|
||||
{InlineHintAttribute, "inlinehint"},
|
||||
{InRegAttribute, "inreg"},
|
||||
@ -78,6 +79,7 @@ func TestAttributes(t *testing.T) {
|
||||
{ReturnedAttribute, "returned"},
|
||||
{ReturnsTwiceAttribute, "returns_twice"},
|
||||
{SExtAttribute, "signext"},
|
||||
{SafeStackAttribute, "safestack"},
|
||||
{StackProtectAttribute, "ssp"},
|
||||
{StackProtectReqAttribute, "sspreq"},
|
||||
{StackProtectStrongAttribute, "sspstrong"},
|
||||
|
@ -277,6 +277,8 @@ uninstall-local:: uninstall-deplibs
|
||||
|
||||
build-deplibs: $(OutputLibs)
|
||||
|
||||
$(OcamlDir)/%.so: $(LibDir)/%.so
|
||||
$(Verb) ln -sf $< $@
|
||||
$(OcamlDir)/%.a: $(LibDir)/%.a
|
||||
$(Verb) ln -sf $< $@
|
||||
|
||||
|
@ -43,11 +43,11 @@ external run_static_dtors : llexecutionengine -> unit
|
||||
= "llvm_ee_run_static_dtors"
|
||||
external data_layout : llexecutionengine -> Llvm_target.DataLayout.t
|
||||
= "llvm_ee_get_data_layout"
|
||||
external add_global_mapping_ : Llvm.llvalue -> int64 -> llexecutionengine -> unit
|
||||
external add_global_mapping_ : Llvm.llvalue -> nativeint -> llexecutionengine -> unit
|
||||
= "llvm_ee_add_global_mapping"
|
||||
external get_global_value_address_ : string -> llexecutionengine -> int64
|
||||
external get_global_value_address_ : string -> llexecutionengine -> nativeint
|
||||
= "llvm_ee_get_global_value_address"
|
||||
external get_function_address_ : string -> llexecutionengine -> int64
|
||||
external get_function_address_ : string -> llexecutionengine -> nativeint
|
||||
= "llvm_ee_get_function_address"
|
||||
|
||||
let add_global_mapping llval ptr ee =
|
||||
@ -55,14 +55,14 @@ let add_global_mapping llval ptr ee =
|
||||
|
||||
let get_global_value_address name typ ee =
|
||||
let vptr = get_global_value_address_ name ee in
|
||||
if Int64.to_int vptr <> 0 then
|
||||
if Nativeint.to_int vptr <> 0 then
|
||||
let open Ctypes in !@ (coerce (ptr void) (ptr typ) (ptr_of_raw_address vptr))
|
||||
else
|
||||
raise (Error ("Value " ^ name ^ " not found"))
|
||||
|
||||
let get_function_address name typ ee =
|
||||
let fptr = get_function_address_ name ee in
|
||||
if Int64.to_int fptr <> 0 then
|
||||
if Nativeint.to_int fptr <> 0 then
|
||||
let open Ctypes in coerce (ptr void) typ (ptr_of_raw_address fptr)
|
||||
else
|
||||
raise (Error ("Function " ^ name ^ " not found"))
|
||||
|
@ -371,14 +371,6 @@ class Relocation(LLVMObject):
|
||||
|
||||
self.expired = False
|
||||
|
||||
@CachedProperty
|
||||
def address(self):
|
||||
"""The address of this relocation, in long bytes."""
|
||||
if self.expired:
|
||||
raise Exception('Relocation instance has expired.')
|
||||
|
||||
return lib.LLVMGetRelocationAddress(self)
|
||||
|
||||
@CachedProperty
|
||||
def offset(self):
|
||||
"""The offset of this relocation, in long bytes."""
|
||||
@ -498,9 +490,6 @@ def register_library(library):
|
||||
library.LLVMGetSymbolSize.argtypes = [Symbol]
|
||||
library.LLVMGetSymbolSize.restype = c_uint64
|
||||
|
||||
library.LLVMGetRelocationAddress.argtypes = [c_object_p]
|
||||
library.LLVMGetRelocationAddress.restype = c_uint64
|
||||
|
||||
library.LLVMGetRelocationOffset.argtypes = [c_object_p]
|
||||
library.LLVMGetRelocationOffset.restype = c_uint64
|
||||
|
||||
|
@ -358,6 +358,10 @@ elseif (LLVM_NATIVE_ARCH MATCHES "hexagon")
|
||||
set(LLVM_NATIVE_ARCH Hexagon)
|
||||
elseif (LLVM_NATIVE_ARCH MATCHES "s390x")
|
||||
set(LLVM_NATIVE_ARCH SystemZ)
|
||||
elseif (LLVM_NATIVE_ARCH MATCHES "wasm32")
|
||||
set(LLVM_NATIVE_ARCH WebAssembly)
|
||||
elseif (LLVM_NATIVE_ARCH MATCHES "wasm64")
|
||||
set(LLVM_NATIVE_ARCH WebAssembly)
|
||||
else ()
|
||||
message(FATAL_ERROR "Unknown architecture ${LLVM_NATIVE_ARCH}")
|
||||
endif ()
|
||||
@ -393,12 +397,10 @@ else ()
|
||||
endif ()
|
||||
|
||||
if( MINGW )
|
||||
set(HAVE_LIBIMAGEHLP 1)
|
||||
set(HAVE_LIBPSAPI 1)
|
||||
set(HAVE_LIBSHELL32 1)
|
||||
# TODO: Check existence of libraries.
|
||||
# include(CheckLibraryExists)
|
||||
# CHECK_LIBRARY_EXISTS(imagehlp ??? . HAVE_LIBIMAGEHLP)
|
||||
endif( MINGW )
|
||||
|
||||
if (NOT HAVE_STRTOLL)
|
||||
@ -489,7 +491,7 @@ if (LLVM_ENABLE_DOXYGEN)
|
||||
|
||||
option(LLVM_DOXYGEN_EXTERNAL_SEARCH "Enable doxygen external search." OFF)
|
||||
if (LLVM_DOXYGEN_EXTERNAL_SEARCH)
|
||||
set(LLVM_DOXYGEN_SEARCHENGINE_URL "" CACHE STRING "URL to use for external searhc.")
|
||||
set(LLVM_DOXYGEN_SEARCHENGINE_URL "" CACHE STRING "URL to use for external search.")
|
||||
set(LLVM_DOXYGEN_SEARCH_MAPPINGS "" CACHE STRING "Doxygen Search Mappings")
|
||||
endif()
|
||||
endif()
|
||||
@ -546,13 +548,13 @@ else()
|
||||
if( OCAML_VERSION VERSION_LESS "4.00.0" )
|
||||
message(STATUS "OCaml bindings disabled, need OCaml >=4.00.0.")
|
||||
else()
|
||||
find_ocamlfind_package(ctypes VERSION 0.3 OPTIONAL)
|
||||
find_ocamlfind_package(ctypes VERSION 0.4 OPTIONAL)
|
||||
if( HAVE_OCAML_CTYPES )
|
||||
message(STATUS "OCaml bindings enabled.")
|
||||
find_ocamlfind_package(oUnit VERSION 2 OPTIONAL)
|
||||
set(LLVM_BINDINGS "${LLVM_BINDINGS} ocaml")
|
||||
else()
|
||||
message(STATUS "OCaml bindings disabled, need ctypes >=0.3.")
|
||||
message(STATUS "OCaml bindings disabled, need ctypes >=0.4.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
@ -1,4 +1,3 @@
|
||||
include(LLVMParseArguments)
|
||||
include(LLVMProcessSources)
|
||||
include(LLVM-Config)
|
||||
|
||||
@ -84,25 +83,19 @@ function(add_llvm_symbol_exports target_name export_file)
|
||||
DEPENDS ${export_file}
|
||||
VERBATIM
|
||||
COMMENT "Creating export file for ${target_name}")
|
||||
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
|
||||
LINK_FLAGS " -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
|
||||
if (${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
|
||||
LINK_FLAGS " -Wl,-M,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
|
||||
else()
|
||||
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
|
||||
LINK_FLAGS " -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/${native_export_file}")
|
||||
endif()
|
||||
else()
|
||||
set(native_export_file "${target_name}.def")
|
||||
|
||||
set(CAT "cat")
|
||||
set(export_file_nativeslashes ${export_file})
|
||||
if(WIN32 AND NOT CYGWIN AND NOT MSYS)
|
||||
set(CAT "type")
|
||||
# Convert ${export_file} to native format (backslashes) for "type"
|
||||
# Does not use file(TO_NATIVE_PATH) as it doesn't create a native
|
||||
# path but a build-system specific format (see CMake bug
|
||||
# http://public.kitware.com/Bug/print_bug_page.php?bug_id=5939 )
|
||||
string(REPLACE / \\ export_file_nativeslashes ${export_file})
|
||||
endif()
|
||||
|
||||
add_custom_command(OUTPUT ${native_export_file}
|
||||
COMMAND ${CMAKE_COMMAND} -E echo "EXPORTS" > ${native_export_file}
|
||||
COMMAND ${CAT} ${export_file_nativeslashes} >> ${native_export_file}
|
||||
COMMAND ${PYTHON_EXECUTABLE} -c "import sys;print(''.join(['EXPORTS\\n']+sys.stdin.readlines(),))"
|
||||
< ${export_file} > ${native_export_file}
|
||||
DEPENDS ${export_file}
|
||||
VERBATIM
|
||||
COMMENT "Creating export file for ${target_name}")
|
||||
@ -164,7 +157,7 @@ function(add_link_opts target_name)
|
||||
|
||||
# Pass -O3 to the linker. This enabled different optimizations on different
|
||||
# linkers.
|
||||
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32))
|
||||
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin|SunOS" OR WIN32))
|
||||
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
|
||||
LINK_FLAGS " -Wl,-O3")
|
||||
endif()
|
||||
@ -182,6 +175,9 @@ function(add_link_opts target_name)
|
||||
# ld64's implementation of -dead_strip breaks tools that use plugins.
|
||||
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
|
||||
LINK_FLAGS " -Wl,-dead_strip")
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
|
||||
set_property(TARGET ${target_name} APPEND_STRING PROPERTY
|
||||
LINK_FLAGS " -Wl,-z -Wl,discard-unused=sections")
|
||||
elseif(NOT WIN32 AND NOT LLVM_LINKER_IS_GOLD)
|
||||
# Object files are compiled with -ffunction-data-sections.
|
||||
# Versions of bfd ld < 2.23.1 have a bug in --gc-sections that breaks
|
||||
@ -286,6 +282,8 @@ function(set_windows_version_resource_properties name resource_file)
|
||||
set(ARG_PRODUCT_NAME "LLVM")
|
||||
endif()
|
||||
|
||||
set_property(SOURCE ${resource_file}
|
||||
PROPERTY COMPILE_FLAGS /nologo)
|
||||
set_property(SOURCE ${resource_file}
|
||||
PROPERTY COMPILE_DEFINITIONS
|
||||
"RC_VERSION_FIELD_1=${ARG_VERSION_MAJOR}"
|
||||
@ -494,11 +492,17 @@ macro(add_llvm_library name)
|
||||
else()
|
||||
llvm_add_library(${name} ${ARGN})
|
||||
endif()
|
||||
set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} )
|
||||
# The gtest libraries should not be installed or exported as a target
|
||||
if ("${name}" STREQUAL gtest OR "${name}" STREQUAL gtest_main)
|
||||
set(_is_gtest TRUE)
|
||||
else()
|
||||
set(_is_gtest FALSE)
|
||||
set_property( GLOBAL APPEND PROPERTY LLVM_LIBS ${name} )
|
||||
endif()
|
||||
|
||||
if( EXCLUDE_FROM_ALL )
|
||||
set_target_properties( ${name} PROPERTIES EXCLUDE_FROM_ALL ON)
|
||||
else()
|
||||
elseif(NOT _is_gtest)
|
||||
if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "LTO")
|
||||
if(ARG_SHARED OR BUILD_SHARED_LIBS)
|
||||
if(WIN32 OR CYGWIN)
|
||||
@ -672,6 +676,13 @@ macro(add_llvm_target target_name)
|
||||
set( CURRENT_LLVM_TARGET LLVM${target_name} )
|
||||
endmacro(add_llvm_target)
|
||||
|
||||
function(canonicalize_tool_name name output)
|
||||
string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}/" "" nameStrip ${name})
|
||||
string(REPLACE "-" "_" nameUNDERSCORE ${nameStrip})
|
||||
string(TOUPPER ${nameUNDERSCORE} nameUPPER)
|
||||
set(${output} "${nameUPPER}" PARENT_SCOPE)
|
||||
endfunction(canonicalize_tool_name)
|
||||
|
||||
# Add external project that may want to be built as part of llvm such as Clang,
|
||||
# lld, and Polly. This adds two options. One for the source directory of the
|
||||
# project, which defaults to ${CMAKE_CURRENT_SOURCE_DIR}/${name}. Another to
|
||||
@ -682,38 +693,68 @@ macro(add_llvm_external_project name)
|
||||
if("${add_llvm_external_dir}" STREQUAL "")
|
||||
set(add_llvm_external_dir ${name})
|
||||
endif()
|
||||
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}")
|
||||
string(REPLACE "-" "_" nameUNDERSCORE ${name})
|
||||
string(TOUPPER ${nameUNDERSCORE} nameUPPER)
|
||||
set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}"
|
||||
CACHE PATH "Path to ${name} source directory")
|
||||
if (NOT ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} STREQUAL ""
|
||||
AND EXISTS ${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}/CMakeLists.txt)
|
||||
option(LLVM_EXTERNAL_${nameUPPER}_BUILD
|
||||
"Whether to build ${name} as part of LLVM" ON)
|
||||
if (LLVM_EXTERNAL_${nameUPPER}_BUILD)
|
||||
canonicalize_tool_name(${name} nameUPPER)
|
||||
if(NOT DEFINED LLVM_TOOL_${nameUPPER}_BUILD)
|
||||
option(LLVM_TOOL_${nameUPPER}_BUILD
|
||||
"Whether to build ${name} as part of LLVM" On)
|
||||
endif()
|
||||
if (LLVM_TOOL_${nameUPPER}_BUILD)
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir}/CMakeLists.txt)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${add_llvm_external_dir} ${add_llvm_external_dir})
|
||||
set(LLVM_TOOL_${nameUPPER}_BUILD Off)
|
||||
elseif(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR)
|
||||
set(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR
|
||||
"${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR}"
|
||||
CACHE PATH "Path to ${name} source directory")
|
||||
mark_as_advanced(LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR)
|
||||
add_subdirectory(${LLVM_EXTERNAL_${nameUPPER}_SOURCE_DIR} ${add_llvm_external_dir})
|
||||
set(LLVM_TOOL_${nameUPPER}_BUILD Off)
|
||||
endif()
|
||||
endif()
|
||||
endmacro(add_llvm_external_project)
|
||||
|
||||
macro(add_llvm_tool_subdirectory name)
|
||||
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}")
|
||||
add_subdirectory(${name})
|
||||
add_llvm_external_project(${name})
|
||||
endmacro(add_llvm_tool_subdirectory)
|
||||
|
||||
macro(ignore_llvm_tool_subdirectory name)
|
||||
list(APPEND LLVM_IMPLICIT_PROJECT_IGNORE "${CMAKE_CURRENT_SOURCE_DIR}/${name}")
|
||||
endmacro(ignore_llvm_tool_subdirectory)
|
||||
function(get_project_name_from_src_var var output)
|
||||
string(REGEX MATCH "LLVM_EXTERNAL_(.*)_SOURCE_DIR"
|
||||
MACHED_TOOL "${var}")
|
||||
if(MACHED_TOOL)
|
||||
set(${output} ${CMAKE_MATCH_1} PARENT_SCOPE)
|
||||
else()
|
||||
set(${output} PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(add_llvm_implicit_external_projects)
|
||||
function(create_llvm_tool_options)
|
||||
file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*")
|
||||
foreach(dir ${sub-dirs})
|
||||
if(IS_DIRECTORY "${dir}" AND EXISTS "${dir}/CMakeLists.txt")
|
||||
canonicalize_tool_name(${dir} name)
|
||||
option(LLVM_TOOL_${name}_BUILD
|
||||
"Whether to build ${name} as part of LLVM" On)
|
||||
mark_as_advanced(LLVM_TOOL_${name}_BUILD)
|
||||
endif()
|
||||
endforeach()
|
||||
get_cmake_property(variableNames VARIABLES)
|
||||
foreach (variableName ${variableNames})
|
||||
get_project_name_from_src_var(${variableName} projectName)
|
||||
if(projectName)
|
||||
option(LLVM_TOOL_${projectName}_BUILD
|
||||
"Whether to build ${name} as part of LLVM" On)
|
||||
mark_as_advanced(LLVM_TOOL_${name}_BUILD)
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction(create_llvm_tool_options)
|
||||
|
||||
function(add_llvm_implicit_projects)
|
||||
set(list_of_implicit_subdirs "")
|
||||
file(GLOB sub-dirs "${CMAKE_CURRENT_SOURCE_DIR}/*")
|
||||
foreach(dir ${sub-dirs})
|
||||
if(IS_DIRECTORY "${dir}")
|
||||
list(FIND LLVM_IMPLICIT_PROJECT_IGNORE "${dir}" tool_subdir_ignore)
|
||||
if( tool_subdir_ignore EQUAL -1
|
||||
AND EXISTS "${dir}/CMakeLists.txt")
|
||||
if(IS_DIRECTORY "${dir}" AND EXISTS "${dir}/CMakeLists.txt")
|
||||
canonicalize_tool_name(${dir} name)
|
||||
if (LLVM_TOOL_${name}_BUILD)
|
||||
get_filename_component(fn "${dir}" NAME)
|
||||
list(APPEND list_of_implicit_subdirs "${fn}")
|
||||
endif()
|
||||
@ -723,7 +764,7 @@ function(add_llvm_implicit_external_projects)
|
||||
foreach(external_proj ${list_of_implicit_subdirs})
|
||||
add_llvm_external_project("${external_proj}")
|
||||
endforeach()
|
||||
endfunction(add_llvm_implicit_external_projects)
|
||||
endfunction(add_llvm_implicit_projects)
|
||||
|
||||
# Generic support for adding a unittest.
|
||||
function(add_unittest test_suite test_name)
|
||||
@ -774,7 +815,7 @@ function(llvm_add_go_executable binary pkgpath)
|
||||
endforeach(d)
|
||||
set(ldflags "${CMAKE_EXE_LINKER_FLAGS}")
|
||||
add_custom_command(OUTPUT ${binpath}
|
||||
COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}"
|
||||
COMMAND ${CMAKE_BINARY_DIR}/bin/llvm-go "go=${GO_EXECUTABLE}" "cc=${cc}" "cxx=${cxx}" "cppflags=${cppflags}" "ldflags=${ldflags}"
|
||||
${ARG_GOFLAGS} build -o ${binpath} ${pkgpath}
|
||||
DEPENDS llvm-config ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX}
|
||||
${llvmlibs} ${ARG_DEPENDS}
|
||||
@ -845,7 +886,7 @@ endfunction()
|
||||
# A raw function to create a lit target. This is used to implement the testuite
|
||||
# management functions.
|
||||
function(add_lit_target target comment)
|
||||
parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN})
|
||||
cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
|
||||
set(LIT_ARGS "${ARG_ARGS} ${LLVM_LIT_ARGS}")
|
||||
separate_arguments(LIT_ARGS)
|
||||
if (NOT CMAKE_CFG_INTDIR STREQUAL ".")
|
||||
@ -860,9 +901,9 @@ function(add_lit_target target comment)
|
||||
foreach(param ${ARG_PARAMS})
|
||||
list(APPEND LIT_COMMAND --param ${param})
|
||||
endforeach()
|
||||
if (ARG_DEFAULT_ARGS)
|
||||
if (ARG_UNPARSED_ARGUMENTS)
|
||||
add_custom_target(${target}
|
||||
COMMAND ${LIT_COMMAND} ${ARG_DEFAULT_ARGS}
|
||||
COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS}
|
||||
COMMENT "${comment}"
|
||||
${cmake_3_2_USES_TERMINAL}
|
||||
)
|
||||
@ -881,12 +922,12 @@ endfunction()
|
||||
|
||||
# A function to add a set of lit test suites to be driven through 'check-*' targets.
|
||||
function(add_lit_testsuite target comment)
|
||||
parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN})
|
||||
cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
|
||||
|
||||
# EXCLUDE_FROM_ALL excludes the test ${target} out of check-all.
|
||||
if(NOT EXCLUDE_FROM_ALL)
|
||||
# Register the testsuites, params and depends for the global check rule.
|
||||
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_TESTSUITES ${ARG_DEFAULT_ARGS})
|
||||
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_TESTSUITES ${ARG_UNPARSED_ARGUMENTS})
|
||||
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_PARAMS ${ARG_PARAMS})
|
||||
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_DEPENDS ${ARG_DEPENDS})
|
||||
set_property(GLOBAL APPEND PROPERTY LLVM_LIT_EXTRA_ARGS ${ARG_ARGS})
|
||||
@ -894,7 +935,7 @@ function(add_lit_testsuite target comment)
|
||||
|
||||
# Produce a specific suffixed check rule.
|
||||
add_lit_target(${target} ${comment}
|
||||
${ARG_DEFAULT_ARGS}
|
||||
${ARG_UNPARSED_ARGUMENTS}
|
||||
PARAMS ${ARG_PARAMS}
|
||||
DEPENDS ${ARG_DEPENDS}
|
||||
ARGS ${ARG_ARGS}
|
||||
@ -903,7 +944,7 @@ endfunction()
|
||||
|
||||
function(add_lit_testsuites project directory)
|
||||
if (NOT CMAKE_CONFIGURATION_TYPES)
|
||||
parse_arguments(ARG "PARAMS;DEPENDS;ARGS" "" ${ARGN})
|
||||
cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
|
||||
file(GLOB_RECURSE litCfg ${directory}/lit*.cfg)
|
||||
set(lit_suites)
|
||||
foreach(f ${litCfg})
|
||||
|
@ -2,15 +2,45 @@
|
||||
|
||||
INCLUDE(CheckCXXSourceCompiles)
|
||||
|
||||
check_function_exists(__atomic_fetch_add_4 HAVE___ATOMIC_FETCH_ADD_4)
|
||||
if( NOT HAVE___ATOMIC_FETCH_ADD_4 )
|
||||
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
|
||||
set(HAVE_LIBATOMIC False)
|
||||
if( HAVE_LIBATOMIC )
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
# Sometimes linking against libatomic is required for atomic ops, if
|
||||
# the platform doesn't support lock-free atomics.
|
||||
|
||||
function(check_working_cxx_atomics varname)
|
||||
set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
|
||||
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#include <atomic>
|
||||
std::atomic<int> x;
|
||||
int main() {
|
||||
return x;
|
||||
}
|
||||
" ${varname})
|
||||
set(CMAKE_REQUIRED_FLAGS ${OLD_CMAKE_REQUIRED_FLAGS})
|
||||
endfunction(check_working_cxx_atomics)
|
||||
|
||||
# This isn't necessary on MSVC, so avoid command-line switch annoyance
|
||||
# by only running on GCC-like hosts.
|
||||
if (LLVM_COMPILER_IS_GCC_COMPATIBLE)
|
||||
# First check if atomics work without the library.
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
# If not, check if the library exists, and atomics work with it.
|
||||
if(NOT HAVE_CXX_ATOMICS_WITHOUT_LIB)
|
||||
check_library_exists(atomic __atomic_fetch_add_4 "" HAVE_LIBATOMIC)
|
||||
if( HAVE_LIBATOMIC )
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES "atomic")
|
||||
check_working_cxx_atomics(HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
if (NOT HAVE_CXX_ATOMICS_WITH_LIB)
|
||||
message(FATAL_ERROR "Host compiler must support std::atomic!")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Host compiler appears to require libatomic, but cannot find it.")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
## TODO: This define is only used for the legacy atomic operations in
|
||||
## llvm's Atomic.h, which should be replaced. Other code simply
|
||||
## assumes C++11 <atomic> works.
|
||||
CHECK_CXX_SOURCE_COMPILES("
|
||||
#ifdef _MSC_VER
|
||||
#include <Intrin.h> /* Workaround for PR19898. */
|
||||
|
@ -131,7 +131,7 @@ endif()
|
||||
|
||||
# Pass -Wl,-z,defs. This makes sure all symbols are defined. Otherwise a DSO
|
||||
# build might work on ELF but fail on MachO/COFF.
|
||||
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR
|
||||
if(NOT (${CMAKE_SYSTEM_NAME} MATCHES "Darwin" OR WIN32 OR CYGWIN OR
|
||||
${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") AND
|
||||
NOT LLVM_USE_SANITIZER)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,defs")
|
||||
@ -166,6 +166,7 @@ function(add_flag_or_print_warning flag name)
|
||||
message(STATUS "Building with ${flag}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}" PARENT_SCOPE)
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} ${flag}" PARENT_SCOPE)
|
||||
else()
|
||||
message(WARNING "${flag} is not supported.")
|
||||
endif()
|
||||
@ -307,10 +308,12 @@ if( MSVC )
|
||||
-wd4611 # Suppress 'interaction between '_setjmp' and C++ object destruction is non-portable'
|
||||
-wd4805 # Suppress 'unsafe mix of type <type> and type <type> in operation'
|
||||
-wd4204 # Suppress 'nonstandard extension used : non-constant aggregate initializer'
|
||||
-wd4577 # Suppress 'noexcept used with no exception handling mode specified; termination on exception is not guaranteed'
|
||||
-wd4091 # Suppress 'typedef: ignored on left of '' when no variable is declared'
|
||||
|
||||
# Idelly, we'd like this warning to be enabled, but MSVC 2013 doesn't
|
||||
# Ideally, we'd like this warning to be enabled, but MSVC 2013 doesn't
|
||||
# support the 'aligned' attribute in the way that clang sources requires (for
|
||||
# any code that uses the LLVM_ALIGNAS marco), so this is must be disabled to
|
||||
# any code that uses the LLVM_ALIGNAS macro), so this is must be disabled to
|
||||
# avoid unwanted alignment warnings.
|
||||
# When we switch to requiring a version of MSVC that supports the 'alignas'
|
||||
# specifier (MSVC 2015?) this warning can be re-enabled.
|
||||
|
@ -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)
|
@ -47,6 +47,12 @@ ifeq ($(LLVM_LIBS_TO_EXPORT),Error)
|
||||
$(error llvm-config --libs failed)
|
||||
endif
|
||||
|
||||
# Strip out gtest and gtest_main from LLVM_LIBS_TO_EXPORT, these are not
|
||||
# installed and won't be available from the install tree.
|
||||
# FIXME: If we used llvm-config from the install tree this wouldn't be
|
||||
# necessary.
|
||||
LLVM_LIBS_TO_EXPORT := $(filter-out gtest gtest_main,$(LLVM_LIBS_TO_EXPORT))
|
||||
|
||||
ifndef LLVM_LIBS_TO_EXPORT
|
||||
$(error LLVM_LIBS_TO_EXPORT cannot be empty)
|
||||
endif
|
||||
@ -54,11 +60,27 @@ endif
|
||||
|
||||
OBJMODS := LLVMConfig.cmake LLVMConfigVersion.cmake LLVMExports.cmake
|
||||
|
||||
LLVM_CONFIG_CODE := \
|
||||
\# Compute the CMake directory from the LLVMConfig.cmake file location.\n\
|
||||
get_filename_component(_LLVM_CMAKE_DIR "$${CMAKE_CURRENT_LIST_FILE}" PATH)\n\
|
||||
\# Compute the installation prefix from the LLVMConfig.cmake file location.\n\
|
||||
get_filename_component(LLVM_INSTALL_PREFIX "$${CMAKE_CURRENT_LIST_FILE}" PATH)\n
|
||||
|
||||
# Compute number of levels (typically 3 - ``share/llvm/cmake/``) to PROJ_prefix
|
||||
# from PROJ_cmake, then emit the appropriate number of calls to
|
||||
# get_filename_components(). Note this assumes there are no spaces in the
|
||||
# cmake_path_suffix variable.
|
||||
cmake_path_suffix := $(subst $(PROJ_prefix),,$(subst $(DESTDIR),,$(PROJ_cmake)))
|
||||
cmake_path_dirs := $(subst /, ,$(cmake_path_suffix))
|
||||
LLVM_CONFIG_CODE += $(foreach __not_used,$(cmake_path_dirs),get_filename_component(LLVM_INSTALL_PREFIX "$${LLVM_INSTALL_PREFIX}" PATH)\n)
|
||||
|
||||
LLVM_CONFIG_CODE += set(_LLVM_LIBRARY_DIR "$${LLVM_INSTALL_PREFIX}\/lib")
|
||||
|
||||
$(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeFrag)
|
||||
$(Echo) 'Generating LLVM CMake package config file'
|
||||
$(Verb) ( \
|
||||
cat $< | sed \
|
||||
-e 's/@LLVM_CONFIG_CODE@/set(LLVM_INSTALL_PREFIX "'"$(subst /,\/,$(PROJ_prefix))"'")/' \
|
||||
-e 's/@LLVM_CONFIG_CODE@/$(LLVM_CONFIG_CODE)/' \
|
||||
-e 's/@LLVM_VERSION_MAJOR@/'"$(LLVM_VERSION_MAJOR)"'/' \
|
||||
-e 's/@LLVM_VERSION_MINOR@/'"$(LLVM_VERSION_MINOR)"'/' \
|
||||
-e 's/@LLVM_VERSION_PATCH@/'"$(LLVM_VERSION_PATCH)"'/' \
|
||||
@ -81,17 +103,20 @@ $(PROJ_OBJ_DIR)/LLVMConfig.cmake: LLVMConfig.cmake.in Makefile $(LLVMBuildCMakeF
|
||||
-e 's/@LLVM_ON_UNIX@/'"$(LLVM_ON_UNIX)"'/' \
|
||||
-e 's/@LLVM_ON_WIN32@/'"$(LLVM_ON_WIN32)"'/' \
|
||||
-e 's/@LLVM_LIBDIR_SUFFIX@//' \
|
||||
-e 's/@LLVM_CONFIG_INCLUDE_DIRS@/'"$(subst /,\/,$(PROJ_includedir))"'/' \
|
||||
-e 's/@LLVM_CONFIG_LIBRARY_DIRS@/'"$(subst /,\/,$(PROJ_libdir))"'/' \
|
||||
-e 's/@LLVM_CONFIG_CMAKE_DIR@/'"$(subst /,\/,$(PROJ_cmake))"'/' \
|
||||
-e 's/@LLVM_CONFIG_TOOLS_BINARY_DIR@/'"$(subst /,\/,$(PROJ_bindir))"'/' \
|
||||
-e 's#@LLVM_CONFIG_INCLUDE_DIRS@#$${LLVM_INSTALL_PREFIX}/include#' \
|
||||
-e 's#@LLVM_CONFIG_LIBRARY_DIRS@#$${_LLVM_LIBRARY_DIR}#' \
|
||||
-e 's#@LLVM_CONFIG_CMAKE_DIR@#$${_LLVM_CMAKE_DIR}#' \
|
||||
-e 's#@LLVM_CONFIG_TOOLS_BINARY_DIR@#$${LLVM_INSTALL_PREFIX}/bin#' \
|
||||
-e 's/@LLVM_CONFIG_EXPORTS_FILE@/$${LLVM_CMAKE_DIR}\/LLVMExports.cmake/' \
|
||||
-e 's/@all_llvm_lib_deps@//' \
|
||||
&& \
|
||||
grep '^set_property.*LLVMBUILD_LIB_DEPS_' "$(LLVMBuildCMakeFrag)" \
|
||||
( grep '^set_property.*LLVMBUILD_LIB_DEPS_' "$(LLVMBuildCMakeFrag)" | \
|
||||
grep -v LLVMBUILD_LIB_DEPS_gtest ) && \
|
||||
echo 'unset(_LLVM_CMAKE_DIR)' && \
|
||||
echo 'unset(_LLVM_LIBRARY_DIR)' \
|
||||
) > $@
|
||||
|
||||
$(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in
|
||||
$(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in Makefile
|
||||
$(Echo) 'Generating LLVM CMake package version file'
|
||||
$(Verb) cat $< | sed \
|
||||
-e 's/@PACKAGE_VERSION@/'"$(LLVMVersion)"'/' \
|
||||
@ -100,13 +125,13 @@ $(PROJ_OBJ_DIR)/LLVMConfigVersion.cmake: LLVMConfigVersion.cmake.in
|
||||
-e 's/@LLVM_VERSION_PATCH@/'"$(LLVM_VERSION_PATCH)"'/' \
|
||||
> $@
|
||||
|
||||
$(PROJ_OBJ_DIR)/LLVMExports.cmake: $(LLVMBuildCMakeExportsFrag)
|
||||
$(PROJ_OBJ_DIR)/LLVMExports.cmake: $(LLVMBuildCMakeExportsFrag) Makefile
|
||||
$(Echo) 'Generating LLVM CMake target exports file'
|
||||
$(Verb) ( \
|
||||
echo '# LLVM CMake target exports. Do not include directly.' && \
|
||||
for lib in $(LLVM_LIBS_TO_EXPORT); do \
|
||||
echo 'add_library('"$$lib"' STATIC IMPORTED)' && \
|
||||
echo 'set_property(TARGET '"$$lib"' PROPERTY IMPORTED_LOCATION "'"$(PROJ_libdir)/lib$$lib.a"'")' ; \
|
||||
echo 'set_property(TARGET '"$$lib"' PROPERTY IMPORTED_LOCATION "$${_LLVM_LIBRARY_DIR}/'lib$$lib.a'")' ; \
|
||||
done && \
|
||||
cat "$(LLVMBuildCMakeExportsFrag)" && \
|
||||
echo 'set_property(TARGET LLVMSupport APPEND PROPERTY IMPORTED_LINK_INTERFACE_LIBRARIES '"$(subst -l,,$(LIBS))"')' \
|
||||
|
130
configure
vendored
130
configure
vendored
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.60 for LLVM 3.7.0svn.
|
||||
# Generated by GNU Autoconf 2.60 for LLVM 3.8.0svn.
|
||||
#
|
||||
# Report bugs to <http://llvm.org/bugs/>.
|
||||
#
|
||||
@ -561,8 +561,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='LLVM'
|
||||
PACKAGE_TARNAME='llvm'
|
||||
PACKAGE_VERSION='3.7.0svn'
|
||||
PACKAGE_STRING='LLVM 3.7.0svn'
|
||||
PACKAGE_VERSION='3.8.0svn'
|
||||
PACKAGE_STRING='LLVM 3.8.0svn'
|
||||
PACKAGE_BUGREPORT='http://llvm.org/bugs/'
|
||||
|
||||
ac_unique_file="lib/IR/Module.cpp"
|
||||
@ -1333,7 +1333,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures LLVM 3.7.0svn to adapt to many kinds of systems.
|
||||
\`configure' configures LLVM 3.8.0svn to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@ -1399,7 +1399,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of LLVM 3.7.0svn:";;
|
||||
short | recursive ) echo "Configuration of LLVM 3.8.0svn:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@ -1463,7 +1463,7 @@ Optional Features:
|
||||
target1,target2,... Valid targets are: host, x86,
|
||||
x86_64, sparc, powerpc, arm64, arm, aarch64, mips,
|
||||
hexagon, xcore, msp430, nvptx, systemz, r600, bpf,
|
||||
and cpp (default=all)
|
||||
wasm, and cpp (default=all)
|
||||
--enable-experimental-targets
|
||||
Build experimental host targets: disable or
|
||||
target1,target2,... (default=disable)
|
||||
@ -1583,7 +1583,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
LLVM configure 3.7.0svn
|
||||
LLVM configure 3.8.0svn
|
||||
generated by GNU Autoconf 2.60
|
||||
|
||||
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
@ -1599,7 +1599,7 @@ cat >config.log <<_ACEOF
|
||||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by LLVM $as_me 3.7.0svn, which was
|
||||
It was created by LLVM $as_me 3.8.0svn, which was
|
||||
generated by GNU Autoconf 2.60. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@ -1954,7 +1954,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
||||
|
||||
|
||||
LLVM_VERSION_MAJOR=3
|
||||
LLVM_VERSION_MINOR=7
|
||||
LLVM_VERSION_MINOR=8
|
||||
LLVM_VERSION_PATCH=0
|
||||
LLVM_VERSION_SUFFIX=svn
|
||||
|
||||
@ -2033,24 +2033,9 @@ echo "$as_me: error: Already configured in ${srcdir}" >&2;}
|
||||
fi
|
||||
|
||||
if test ${srcdir} == "." ; then
|
||||
{ echo "$as_me:$LINENO: WARNING: **************************************************************************************" >&5
|
||||
echo "$as_me: WARNING: **************************************************************************************" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: * *" >&5
|
||||
echo "$as_me: WARNING: * *" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: * WARNING *" >&5
|
||||
echo "$as_me: WARNING: * WARNING *" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: * *" >&5
|
||||
echo "$as_me: WARNING: * *" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: * In-source builds are deprecated. *" >&5
|
||||
echo "$as_me: WARNING: * In-source builds are deprecated. *" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: * *" >&5
|
||||
echo "$as_me: WARNING: * *" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: * Please configure from a separate build directory! *" >&5
|
||||
echo "$as_me: WARNING: * Please configure from a separate build directory! *" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: * *" >&5
|
||||
echo "$as_me: WARNING: * *" >&2;}
|
||||
{ echo "$as_me:$LINENO: WARNING: **************************************************************************************" >&5
|
||||
echo "$as_me: WARNING: **************************************************************************************" >&2;}
|
||||
{ { echo "$as_me:$LINENO: error: In-source builds are not allowed. Please configure from a separate build directory!" >&5
|
||||
echo "$as_me: error: In-source builds are not allowed. Please configure from a separate build directory!" >&2;}
|
||||
{ (exit 1); exit 1; }; }
|
||||
fi
|
||||
|
||||
: ${CFLAGS=}
|
||||
@ -4207,6 +4192,7 @@ else
|
||||
hexagon-*) llvm_cv_target_arch="Hexagon" ;;
|
||||
nvptx-*) llvm_cv_target_arch="NVPTX" ;;
|
||||
s390x-*) llvm_cv_target_arch="SystemZ" ;;
|
||||
wasm*-*) llvm_cv_target_arch="WebAssembly" ;;
|
||||
*) llvm_cv_target_arch="Unknown" ;;
|
||||
esac
|
||||
fi
|
||||
@ -4243,6 +4229,7 @@ case $host in
|
||||
msp430-*) host_arch="MSP430" ;;
|
||||
hexagon-*) host_arch="Hexagon" ;;
|
||||
s390x-*) host_arch="SystemZ" ;;
|
||||
wasm*-*) host_arch="WebAssembly" ;;
|
||||
*) host_arch="Unknown" ;;
|
||||
esac
|
||||
|
||||
@ -5169,6 +5156,8 @@ else
|
||||
NVPTX) TARGET_HAS_JIT=0
|
||||
;;
|
||||
SystemZ) TARGET_HAS_JIT=1
|
||||
;;
|
||||
WebAssembly) TARGET_HAS_JIT=0
|
||||
;;
|
||||
*) TARGET_HAS_JIT=0
|
||||
;;
|
||||
@ -5667,6 +5656,7 @@ case "$enableval" in
|
||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
amdgpu) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
|
||||
r600) TARGETS_TO_BUILD="AMDGPU $TARGETS_TO_BUILD" ;;
|
||||
wasm) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;;
|
||||
host) case "$llvm_cv_target_arch" in
|
||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
x86_64) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||
@ -5680,6 +5670,7 @@ case "$enableval" in
|
||||
Hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;;
|
||||
NVPTX) TARGETS_TO_BUILD="NVPTX $TARGETS_TO_BUILD" ;;
|
||||
SystemZ) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||
WebAssembly) TARGETS_TO_BUILD="WebAssembly $TARGETS_TO_BUILD" ;;
|
||||
*) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5
|
||||
echo "$as_me: error: Can not set target to build" >&2;}
|
||||
{ (exit 1); exit 1; }; } ;;
|
||||
@ -8733,6 +8724,87 @@ _ACEOF
|
||||
fi
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for main in -lole32" >&5
|
||||
echo $ECHO_N "checking for main in -lole32... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_lib_ole32_main+set}" = set; then
|
||||
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||
else
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lole32 $LIBS"
|
||||
cat >conftest.$ac_ext <<_ACEOF
|
||||
/* confdefs.h. */
|
||||
_ACEOF
|
||||
cat confdefs.h >>conftest.$ac_ext
|
||||
cat >>conftest.$ac_ext <<_ACEOF
|
||||
/* end confdefs.h. */
|
||||
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
return main ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
rm -f conftest.$ac_objext conftest$ac_exeext
|
||||
if { (ac_try="$ac_link"
|
||||
case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_link") 2>conftest.er1
|
||||
ac_status=$?
|
||||
grep -v '^ *+' conftest.er1 >conftest.err
|
||||
rm -f conftest.er1
|
||||
cat conftest.err >&5
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); } &&
|
||||
{ ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err'
|
||||
{ (case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; } &&
|
||||
{ ac_try='test -s conftest$ac_exeext'
|
||||
{ (case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||
(exit $ac_status); }; }; then
|
||||
ac_cv_lib_ole32_main=yes
|
||||
else
|
||||
echo "$as_me: failed program was:" >&5
|
||||
sed 's/^/| /' conftest.$ac_ext >&5
|
||||
|
||||
ac_cv_lib_ole32_main=no
|
||||
fi
|
||||
|
||||
rm -f core conftest.err conftest.$ac_objext \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ echo "$as_me:$LINENO: result: $ac_cv_lib_ole32_main" >&5
|
||||
echo "${ECHO_T}$ac_cv_lib_ole32_main" >&6; }
|
||||
if test $ac_cv_lib_ole32_main = yes; then
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define HAVE_LIBOLE32 1
|
||||
_ACEOF
|
||||
|
||||
LIBS="-lole32 $LIBS"
|
||||
|
||||
fi
|
||||
|
||||
|
||||
{ echo "$as_me:$LINENO: checking for main in -lpsapi" >&5
|
||||
echo $ECHO_N "checking for main in -lpsapi... $ECHO_C" >&6; }
|
||||
if test "${ac_cv_lib_psapi_main+set}" = set; then
|
||||
@ -18538,7 +18610,7 @@ exec 6>&1
|
||||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by LLVM $as_me 3.7.0svn, which was
|
||||
This file was extended by LLVM $as_me 3.8.0svn, which was
|
||||
generated by GNU Autoconf 2.60. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@ -18591,7 +18663,7 @@ Report bugs to <bug-autoconf@gnu.org>."
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF
|
||||
ac_cs_version="\\
|
||||
LLVM config.status 3.7.0svn
|
||||
LLVM config.status 3.8.0svn
|
||||
configured by $0, generated by GNU Autoconf 2.60,
|
||||
with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
|
||||
|
||||
|
@ -92,3 +92,86 @@ strings:
|
||||
v_mul_i32_i24 v1, v2, v3
|
||||
v_mul_i32_i24_e32 v1, v2, v3
|
||||
v_mul_i32_i24_e64 v1, v2, v3
|
||||
|
||||
Assembler Directives
|
||||
--------------------
|
||||
|
||||
.hsa_code_object_version major, minor
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
*major* and *minor* are integers that specify the version of the HSA code
|
||||
object that will be generated by the assembler. This value will be stored
|
||||
in an entry of the .note section.
|
||||
|
||||
.hsa_code_object_isa [major, minor, stepping, vendor, arch]
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
*major*, *minor*, and *stepping* are all integers that describe the instruction
|
||||
set architecture (ISA) version of the assembly program.
|
||||
|
||||
*vendor* and *arch* are quoted strings. *vendor* should always be equal to
|
||||
"AMD" and *arch* should always be equal to "AMDGPU".
|
||||
|
||||
If no arguments are specified, then the assembler will derive the ISA version,
|
||||
*vendor*, and *arch* from the value of the -mcpu option that is passed to the
|
||||
assembler.
|
||||
|
||||
ISA version, *vendor*, and *arch* will all be stored in a single entry of the
|
||||
.note section.
|
||||
|
||||
.amd_kernel_code_t
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This directive marks the beginning of a list of key / value pairs that are used
|
||||
to specify the amd_kernel_code_t object that will be emitted by the assembler.
|
||||
The list must be terminated by the *.end_amd_kernel_code_t* directive. For
|
||||
any amd_kernel_code_t values that are unspecified a default value will be
|
||||
used. The default value for all keys is 0, with the following exceptions:
|
||||
|
||||
- *kernel_code_version_major* defaults to 1.
|
||||
- *machine_kind* defaults to 1.
|
||||
- *machine_version_major*, *machine_version_minor*, and
|
||||
*machine_version_stepping* are derived from the value of the -mcpu option
|
||||
that is passed to the assembler.
|
||||
- *kernel_code_entry_byte_offset* defaults to 256.
|
||||
- *wavefront_size* defaults to 6.
|
||||
- *kernarg_segment_alignment*, *group_segment_alignment*, and
|
||||
*private_segment_alignment* default to 4. Note that alignments are specified
|
||||
as a power of two, so a value of **n** means an alignment of 2^ **n**.
|
||||
|
||||
The *.amd_kernel_code_t* directive must be placed immediately after the
|
||||
function label and before any instructions.
|
||||
|
||||
For a full list of amd_kernel_code_t keys, see the examples in
|
||||
test/CodeGen/AMDGPU/hsa.s. For an explanation of the meanings of the different
|
||||
keys, see the comments in lib/Target/AMDGPU/AmdKernelCodeT.h
|
||||
|
||||
Here is an example of a minimal amd_kernel_code_t specification:
|
||||
|
||||
.. code-block:: nasm
|
||||
|
||||
.hsa_code_object_version 1,0
|
||||
.hsa_code_object_isa
|
||||
|
||||
.text
|
||||
|
||||
hello_world:
|
||||
|
||||
.amd_kernel_code_t
|
||||
enable_sgpr_kernarg_segment_ptr = 1
|
||||
is_ptr64 = 1
|
||||
compute_pgm_rsrc1_vgprs = 0
|
||||
compute_pgm_rsrc1_sgprs = 0
|
||||
compute_pgm_rsrc2_user_sgpr = 2
|
||||
kernarg_segment_byte_size = 8
|
||||
wavefront_sgpr_count = 2
|
||||
workitem_vgpr_count = 3
|
||||
.end_amd_kernel_code_t
|
||||
|
||||
s_load_dwordx2 s[0:1], s[0:1] 0x0
|
||||
v_mov_b32 v0, 3.14159
|
||||
s_waitcnt lgkmcnt(0)
|
||||
v_mov_b32 v1, s0
|
||||
v_mov_b32 v2, s1
|
||||
flat_store_dword v0, v[1:2]
|
||||
s_endpgm
|
||||
|
@ -286,8 +286,8 @@ Mod/Ref result, simply return whatever the superclass computes. For example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
AliasAnalysis::AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
if (...)
|
||||
return NoAlias;
|
||||
...
|
||||
|
@ -741,7 +741,7 @@ global variable. The operand fields are:
|
||||
MODULE_CODE_FUNCTION Record
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata]``
|
||||
``[FUNCTION, type, callingconv, isproto, linkage, paramattr, alignment, section, visibility, gc, prologuedata, dllstorageclass, comdat, prefixdata, personalityfn]``
|
||||
|
||||
The ``FUNCTION`` record (code 8) marks the declaration or definition of a
|
||||
function. The operand fields are:
|
||||
@ -795,6 +795,8 @@ function. The operand fields are:
|
||||
* *prefixdata*: If non-zero, the value index of the prefix data for this function,
|
||||
plus 1.
|
||||
|
||||
* *personalityfn*: If non-zero, the value index of the personality function for this function,
|
||||
plus 1.
|
||||
|
||||
MODULE_CODE_ALIAS Record
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -327,8 +327,8 @@ LLVM-specific variables
|
||||
|
||||
**LLVM_USE_SANITIZER**:STRING
|
||||
Define the sanitizer used to build LLVM binaries and tests. Possible values
|
||||
are ``Address``, ``Memory``, ``MemoryWithOrigins`` and ``Undefined``.
|
||||
Defaults to empty string.
|
||||
are ``Address``, ``Memory``, ``MemoryWithOrigins``, ``Undefined``, ``Thread``,
|
||||
and ``Address;Undefined``. Defaults to empty string.
|
||||
|
||||
**LLVM_PARALLEL_COMPILE_JOBS**:STRING
|
||||
Define the maximum number of concurrent compilation jobs.
|
||||
|
@ -138,7 +138,9 @@ if( NOT uses_ocaml LESS 0 )
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html
|
||||
COMMAND ${OCAMLFIND} ocamldoc -d ${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html
|
||||
-sort -colorize-code -html ${odoc_files})
|
||||
-sort -colorize-code -html ${odoc_files}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/_ocamldoc/style.css
|
||||
${CMAKE_CURRENT_BINARY_DIR}/ocamldoc/html)
|
||||
|
||||
add_dependencies(ocaml_doc ${doc_targets})
|
||||
|
||||
|
@ -749,7 +749,7 @@ The SelectionDAG is a Directed-Acyclic-Graph whose nodes are instances of the
|
||||
``SDNode`` class. The primary payload of the ``SDNode`` is its operation code
|
||||
(Opcode) that indicates what operation the node performs and the operands to the
|
||||
operation. The various operation node types are described at the top of the
|
||||
``include/llvm/CodeGen/SelectionDAGNodes.h`` file.
|
||||
``include/llvm/CodeGen/ISDOpcodes.h`` file.
|
||||
|
||||
Although most operations define a single value, each node in the graph may
|
||||
define multiple values. For example, a combined div/rem operation will define
|
||||
@ -829,7 +829,7 @@ One great way to visualize what is going on here is to take advantage of a few
|
||||
LLC command line options. The following options pop up a window displaying the
|
||||
SelectionDAG at specific times (if you only get errors printed to the console
|
||||
while using this, you probably `need to configure your
|
||||
system <ProgrammersManual.html#ViewGraph>`_ to add support for it).
|
||||
system <ProgrammersManual.html#viewing-graphs-while-debugging-code>`_ to add support for it).
|
||||
|
||||
* ``-view-dag-combine1-dags`` displays the DAG after being built, before the
|
||||
first optimization pass.
|
||||
|
@ -21,6 +21,7 @@ Basic Commands
|
||||
lli
|
||||
llvm-link
|
||||
llvm-ar
|
||||
llvm-lib
|
||||
llvm-nm
|
||||
llvm-config
|
||||
llvm-diff
|
||||
|
@ -161,7 +161,7 @@ ADDITIONAL OPTIONS
|
||||
|
||||
.. option:: --show-tests
|
||||
|
||||
List all of the the discovered tests and exit.
|
||||
List all of the discovered tests and exit.
|
||||
|
||||
EXIT STATUS
|
||||
-----------
|
||||
|
@ -1,172 +1,127 @@
|
||||
lli - directly execute programs from LLVM bitcode
|
||||
=================================================
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
--------
|
||||
|
||||
|
||||
**lli** [*options*] [*filename*] [*program args*]
|
||||
|
||||
:program:`lli` [*options*] [*filename*] [*program args*]
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
:program:`lli` directly executes programs in LLVM bitcode format. It takes a program
|
||||
in LLVM bitcode format and executes it using a just-in-time compiler or an
|
||||
interpreter.
|
||||
|
||||
**lli** directly executes programs in LLVM bitcode format. It takes a program
|
||||
in LLVM bitcode format and executes it using a just-in-time compiler, if one is
|
||||
available for the current architecture, or an interpreter. **lli** takes all of
|
||||
the same code generator options as llc|llc, but they are only effective when
|
||||
**lli** is using the just-in-time compiler.
|
||||
:program:`lli` is *not* an emulator. It will not execute IR of different architectures
|
||||
and it can only interpret (or JIT-compile) for the host architecture.
|
||||
|
||||
If *filename* is not specified, then **lli** reads the LLVM bitcode for the
|
||||
The JIT compiler takes the same arguments as other tools, like :program:`llc`,
|
||||
but they don't necessarily work for the interpreter.
|
||||
|
||||
If `filename` is not specified, then :program:`lli` reads the LLVM bitcode for the
|
||||
program from standard input.
|
||||
|
||||
The optional *args* specified on the command line are passed to the program as
|
||||
arguments.
|
||||
|
||||
|
||||
GENERAL OPTIONS
|
||||
---------------
|
||||
|
||||
|
||||
|
||||
**-fake-argv0**\ =\ *executable*
|
||||
.. option:: -fake-argv0=executable
|
||||
|
||||
Override the ``argv[0]`` value passed into the executing program.
|
||||
|
||||
|
||||
|
||||
**-force-interpreter**\ =\ *{false,true}*
|
||||
.. option:: -force-interpreter={false,true}
|
||||
|
||||
If set to true, use the interpreter even if a just-in-time compiler is available
|
||||
for this architecture. Defaults to false.
|
||||
|
||||
|
||||
|
||||
**-help**
|
||||
.. option:: -help
|
||||
|
||||
Print a summary of command line options.
|
||||
|
||||
.. option:: -load=pluginfilename
|
||||
|
||||
|
||||
**-load**\ =\ *pluginfilename*
|
||||
|
||||
Causes **lli** to load the plugin (shared object) named *pluginfilename* and use
|
||||
Causes :program:`lli` to load the plugin (shared object) named *pluginfilename* and use
|
||||
it for optimization.
|
||||
|
||||
|
||||
|
||||
**-stats**
|
||||
.. option:: -stats
|
||||
|
||||
Print statistics from the code-generation passes. This is only meaningful for
|
||||
the just-in-time compiler, at present.
|
||||
|
||||
|
||||
|
||||
**-time-passes**
|
||||
.. option:: -time-passes
|
||||
|
||||
Record the amount of time needed for each code-generation pass and print it to
|
||||
standard error.
|
||||
|
||||
.. option:: -version
|
||||
|
||||
|
||||
**-version**
|
||||
|
||||
Print out the version of **lli** and exit without doing anything else.
|
||||
|
||||
|
||||
|
||||
Print out the version of :program:`lli` and exit without doing anything else.
|
||||
|
||||
TARGET OPTIONS
|
||||
--------------
|
||||
|
||||
|
||||
|
||||
**-mtriple**\ =\ *target triple*
|
||||
.. option:: -mtriple=target triple
|
||||
|
||||
Override the target triple specified in the input bitcode file with the
|
||||
specified string. This may result in a crash if you pick an
|
||||
architecture which is not compatible with the current system.
|
||||
|
||||
|
||||
|
||||
**-march**\ =\ *arch*
|
||||
.. option:: -march=arch
|
||||
|
||||
Specify the architecture for which to generate assembly, overriding the target
|
||||
encoded in the bitcode file. See the output of **llc -help** for a list of
|
||||
valid architectures. By default this is inferred from the target triple or
|
||||
autodetected to the current architecture.
|
||||
|
||||
|
||||
|
||||
**-mcpu**\ =\ *cpuname*
|
||||
.. option:: -mcpu=cpuname
|
||||
|
||||
Specify a specific chip in the current architecture to generate code for.
|
||||
By default this is inferred from the target triple and autodetected to
|
||||
the current architecture. For a list of available CPUs, use:
|
||||
**llvm-as < /dev/null | llc -march=xyz -mcpu=help**
|
||||
|
||||
|
||||
|
||||
**-mattr**\ =\ *a1,+a2,-a3,...*
|
||||
.. option:: -mattr=a1,+a2,-a3,...
|
||||
|
||||
Override or control specific attributes of the target, such as whether SIMD
|
||||
operations are enabled or not. The default set of attributes is set by the
|
||||
current CPU. For a list of available attributes, use:
|
||||
**llvm-as < /dev/null | llc -march=xyz -mattr=help**
|
||||
|
||||
|
||||
|
||||
|
||||
FLOATING POINT OPTIONS
|
||||
----------------------
|
||||
|
||||
|
||||
|
||||
**-disable-excess-fp-precision**
|
||||
.. option:: -disable-excess-fp-precision
|
||||
|
||||
Disable optimizations that may increase floating point precision.
|
||||
|
||||
|
||||
|
||||
**-enable-no-infs-fp-math**
|
||||
.. option:: -enable-no-infs-fp-math
|
||||
|
||||
Enable optimizations that assume no Inf values.
|
||||
|
||||
|
||||
|
||||
**-enable-no-nans-fp-math**
|
||||
.. option:: -enable-no-nans-fp-math
|
||||
|
||||
Enable optimizations that assume no NAN values.
|
||||
|
||||
.. option:: -enable-unsafe-fp-math
|
||||
|
||||
|
||||
**-enable-unsafe-fp-math**
|
||||
|
||||
Causes **lli** to enable optimizations that may decrease floating point
|
||||
Causes :program:`lli` to enable optimizations that may decrease floating point
|
||||
precision.
|
||||
|
||||
.. option:: -soft-float
|
||||
|
||||
|
||||
**-soft-float**
|
||||
|
||||
Causes **lli** to generate software floating point library calls instead of
|
||||
Causes :program:`lli` to generate software floating point library calls instead of
|
||||
equivalent hardware instructions.
|
||||
|
||||
|
||||
|
||||
|
||||
CODE GENERATION OPTIONS
|
||||
-----------------------
|
||||
|
||||
|
||||
|
||||
**-code-model**\ =\ *model*
|
||||
.. option:: -code-model=model
|
||||
|
||||
Choose the code model from:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
default: Target default code model
|
||||
@ -175,42 +130,30 @@ CODE GENERATION OPTIONS
|
||||
medium: Medium code model
|
||||
large: Large code model
|
||||
|
||||
|
||||
|
||||
|
||||
**-disable-post-RA-scheduler**
|
||||
.. option:: -disable-post-RA-scheduler
|
||||
|
||||
Disable scheduling after register allocation.
|
||||
|
||||
|
||||
|
||||
**-disable-spill-fusing**
|
||||
.. option:: -disable-spill-fusing
|
||||
|
||||
Disable fusing of spill code into instructions.
|
||||
|
||||
|
||||
|
||||
**-jit-enable-eh**
|
||||
.. option:: -jit-enable-eh
|
||||
|
||||
Exception handling should be enabled in the just-in-time compiler.
|
||||
|
||||
|
||||
|
||||
**-join-liveintervals**
|
||||
.. option:: -join-liveintervals
|
||||
|
||||
Coalesce copies (default=true).
|
||||
|
||||
.. option:: -nozero-initialized-in-bss
|
||||
|
||||
Don't place zero-initialized symbols into the BSS section.
|
||||
|
||||
**-nozero-initialized-in-bss** Don't place zero-initialized symbols into the BSS section.
|
||||
|
||||
|
||||
|
||||
**-pre-RA-sched**\ =\ *scheduler*
|
||||
.. option:: -pre-RA-sched=scheduler
|
||||
|
||||
Instruction schedulers available (before register allocation):
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
=default: Best scheduler for the target
|
||||
@ -221,74 +164,51 @@ CODE GENERATION OPTIONS
|
||||
=list-tdrr: Top-down register reduction list scheduling
|
||||
=list-td: Top-down list scheduler -print-machineinstrs - Print generated machine code
|
||||
|
||||
|
||||
|
||||
|
||||
**-regalloc**\ =\ *allocator*
|
||||
.. option:: -regalloc=allocator
|
||||
|
||||
Register allocator to use (default=linearscan)
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
=bigblock: Big-block register allocator
|
||||
=linearscan: linear scan register allocator =local - local register allocator
|
||||
=simple: simple register allocator
|
||||
|
||||
|
||||
|
||||
|
||||
**-relocation-model**\ =\ *model*
|
||||
.. option:: -relocation-model=model
|
||||
|
||||
Choose relocation model from:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
=default: Target default relocation model
|
||||
=static: Non-relocatable code =pic - Fully relocatable, position independent code
|
||||
=dynamic-no-pic: Relocatable external references, non-relocatable code
|
||||
|
||||
|
||||
|
||||
|
||||
**-spiller**
|
||||
.. option:: -spiller
|
||||
|
||||
Spiller to use (default=local)
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
=simple: simple spiller
|
||||
=local: local spiller
|
||||
|
||||
|
||||
|
||||
|
||||
**-x86-asm-syntax**\ =\ *syntax*
|
||||
.. option:: -x86-asm-syntax=syntax
|
||||
|
||||
Choose style of code to emit from X86 backend:
|
||||
|
||||
|
||||
.. code-block:: perl
|
||||
|
||||
=att: Emit AT&T-style assembly
|
||||
=intel: Emit Intel-style assembly
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
EXIT STATUS
|
||||
-----------
|
||||
|
||||
|
||||
If **lli** fails to load the program, it will exit with an exit code of 1.
|
||||
If :program:`lli` fails to load the program, it will exit with an exit code of 1.
|
||||
Otherwise, it will return the exit code of the program it executes.
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
|
||||
|
||||
llc|llc
|
||||
:program:`llc`
|
||||
|
@ -26,5 +26,5 @@ OPTIONS
|
||||
EXIT STATUS
|
||||
-----------
|
||||
|
||||
:program:`llvm-dwarfdump` returns 0. Other exit codes imply internal
|
||||
program error.
|
||||
:program:`llvm-dwarfdump` returns 0 if the input files were parsed and dumped
|
||||
successfully. Otherwise, it returns 1.
|
||||
|
31
docs/CommandGuide/llvm-lib.rst
Normal file
31
docs/CommandGuide/llvm-lib.rst
Normal 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).
|
@ -1737,6 +1737,7 @@ exported by the ``lib/VMCore/PassManager.cpp`` file.
|
||||
.. _dynamically loaded options:
|
||||
|
||||
Dynamically adding command line options
|
||||
---------------------------------------
|
||||
|
||||
.. todo::
|
||||
|
||||
|
@ -405,7 +405,7 @@ LEB128 is an unsigned interger value that is encoded using DWARF's LEB128
|
||||
encoding, optimizing for the case where values are small
|
||||
(1 byte for values less than 128).
|
||||
|
||||
.. _strings:
|
||||
.. _Strings:
|
||||
|
||||
Strings
|
||||
^^^^^^^
|
||||
|
@ -624,5 +624,5 @@ patent-related trouble with their changes (including from third parties). If
|
||||
you or your employer own the rights to a patent and would like to contribute
|
||||
code to LLVM that relies on it, we require that the copyright owner sign an
|
||||
agreement that allows any other user of LLVM to freely use your patent. Please
|
||||
contact the `oversight group <mailto:llvm-oversight@cs.uiuc.edu>`_ for more
|
||||
contact the `LLVM Foundation Board of Directors <mailto:board@llvm.org>`_ for more
|
||||
details.
|
||||
|
@ -339,11 +339,11 @@ original context before code generation.
|
||||
|
||||
Catch handlers are called with a pointer to the handler itself as the first
|
||||
argument and a pointer to the parent function's stack frame as the second
|
||||
argument. The catch handler uses the `llvm.recoverframe
|
||||
<LangRef.html#llvm-frameallocate-and-llvm-framerecover-intrinsics>`_ to get a
|
||||
argument. The catch handler uses the `llvm.localrecover
|
||||
<LangRef.html#llvm-localescape-and-llvm-localrecover-intrinsics>`_ to get a
|
||||
pointer to a frame allocation block that is created in the parent frame using
|
||||
the `llvm.allocateframe
|
||||
<LangRef.html#llvm-frameallocate-and-llvm-framerecover-intrinsics>`_ intrinsic.
|
||||
the `llvm.localescape
|
||||
<LangRef.html#llvm-localescape-and-llvm-localrecover-intrinsics>`_ intrinsic.
|
||||
The ``WinEHPrepare`` pass will have created a structure definition for the
|
||||
contents of this block. The first two members of the structure will always be
|
||||
(1) a 32-bit integer that the runtime uses to track the exception state of the
|
||||
@ -520,12 +520,12 @@ action.
|
||||
A code of ``i32 1`` indicates a catch action, which expects three additional
|
||||
arguments. Different EH schemes give different meanings to the three arguments,
|
||||
but the first argument indicates whether the catch should fire, the second is
|
||||
the frameescape index of the exception object, and the third is the code to run
|
||||
the localescape index of the exception object, and the third is the code to run
|
||||
to catch the exception.
|
||||
|
||||
For Windows C++ exception handling, the first argument for a catch handler is a
|
||||
pointer to the RTTI type descriptor for the object to catch. The second
|
||||
argument is an index into the argument list of the ``llvm.frameescape`` call in
|
||||
argument is an index into the argument list of the ``llvm.localescape`` call in
|
||||
the main function. The exception object will be copied into the provided stack
|
||||
object. If the exception object is not required, this argument should be -1.
|
||||
The third argument is a pointer to a function implementing the catch. This
|
||||
|
@ -49,6 +49,79 @@ The format of this section is
|
||||
FunctionFaultInfo[NumFaultingPCs] {
|
||||
uint32 : FaultKind = FaultMaps::FaultingLoad (only legal value currently)
|
||||
uint32 : FaultingPCOffset
|
||||
uint32 : handlerPCOffset
|
||||
uint32 : HandlerPCOffset
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
The ``ImplicitNullChecks`` pass
|
||||
===============================
|
||||
|
||||
The ``ImplicitNullChecks`` pass transforms explicit control flow for
|
||||
checking if a pointer is ``null``, like:
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%ptr = call i32* @get_ptr()
|
||||
%ptr_is_null = icmp i32* %ptr, null
|
||||
br i1 %ptr_is_null, label %is_null, label %not_null, !make.implicit !0
|
||||
|
||||
not_null:
|
||||
%t = load i32, i32* %ptr
|
||||
br label %do_something_with_t
|
||||
|
||||
is_null:
|
||||
call void @HFC()
|
||||
unreachable
|
||||
|
||||
!0 = !{}
|
||||
|
||||
to control flow implicit in the instruction loading or storing through
|
||||
the pointer being null checked:
|
||||
|
||||
.. code-block:: llvm
|
||||
|
||||
%ptr = call i32* @get_ptr()
|
||||
%t = load i32, i32* %ptr ;; handler-pc = label %is_null
|
||||
br label %do_something_with_t
|
||||
|
||||
is_null:
|
||||
call void @HFC()
|
||||
unreachable
|
||||
|
||||
This transform happens at the ``MachineInstr`` level, not the LLVM IR
|
||||
level (so the above example is only representative, not literal). The
|
||||
``ImplicitNullChecks`` pass runs during codegen, if
|
||||
``-enable-implicit-null-checks`` is passed to ``llc``.
|
||||
|
||||
The ``ImplicitNullChecks`` pass adds entries to the
|
||||
``__llvm_faultmaps`` section described above as needed.
|
||||
|
||||
``make.implicit`` metadata
|
||||
--------------------------
|
||||
|
||||
Making null checks implicit is an aggressive optimization, and it can
|
||||
be a net performance pessimization if too many memory operations end
|
||||
up faulting because of it. A language runtime typically needs to
|
||||
ensure that only a negligible number of implicit null checks actually
|
||||
fault once the application has reached a steady state. A standard way
|
||||
of doing this is by healing failed implicit null checks into explicit
|
||||
null checks via code patching or recompilation. It follows that there
|
||||
are two requirements an explicit null check needs to satisfy for it to
|
||||
be profitable to convert it to an implicit null check:
|
||||
|
||||
1. The case where the pointer is actually null (i.e. the "failing"
|
||||
case) is extremely rare.
|
||||
|
||||
2. The failing path heals the implicit null check into an explicit
|
||||
null check so that the application does not repeatedly page
|
||||
fault.
|
||||
|
||||
The frontend is expected to mark branches that satisfy (1) and (2)
|
||||
using a ``!make.implicit`` metadata node (the actual content of the
|
||||
metadata node is ignored). Only branches that are marked with
|
||||
``!make.implicit`` metadata are considered as candidates for
|
||||
conversion into implicit null checks.
|
||||
|
||||
(Note that while we could deal with (1) using profiling data, dealing
|
||||
with (2) requires some information not present in branch profiles.)
|
||||
|
@ -326,7 +326,11 @@ Easy steps for installing GCC 4.8.2:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
% wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2
|
||||
% wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2
|
||||
% wget https://ftp.gnu.org/gnu/gcc/gcc-4.8.2/gcc-4.8.2.tar.bz2.sig
|
||||
% wget https://ftp.gnu.org/gnu/gnu-keyring.gpg
|
||||
% signature_invalid=`gpg --verify --no-default-keyring --keyring ./gnu-keyring.gpg gcc-4.8.2.tar.bz2.sig`
|
||||
% if [ $signature_invalid ]; then echo "Invalid signature" ; exit 1 ; fi
|
||||
% tar -xvjf gcc-4.8.2.tar.bz2
|
||||
% cd gcc-4.8.2
|
||||
% ./contrib/download_prerequisites
|
||||
|
@ -136,51 +136,24 @@ Regenerate the configure scripts for both ``llvm`` and the ``test-suite``.
|
||||
In addition, the version numbers of all the Bugzilla components must be updated
|
||||
for the next release.
|
||||
|
||||
Build the LLVM Release Candidates
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Tagging the LLVM Release Candidates
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Create release candidates for ``llvm``, ``clang``, ``dragonegg``, and the LLVM
|
||||
``test-suite`` by tagging the branch with the respective release candidate
|
||||
number. For instance, to create **Release Candidate 1** you would issue the
|
||||
following commands:
|
||||
Tag release candidates using the tag.sh script in utils/release.
|
||||
|
||||
::
|
||||
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ
|
||||
$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/rc1
|
||||
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ
|
||||
$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/rc1
|
||||
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ
|
||||
$ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/rc1
|
||||
|
||||
$ svn mkdir https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ
|
||||
$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/rc1
|
||||
|
||||
Similarly, **Release Candidate 2** would be named ``RC2`` and so on. This keeps
|
||||
a permanent copy of the release candidate around for people to export and build
|
||||
as they wish. The final released sources will be tagged in the ``RELEASE_XYZ``
|
||||
directory as ``Final`` (c.f. :ref:`tag`).
|
||||
$ ./tag.sh -release X.Y.Z -rc $RC
|
||||
|
||||
The Release Manager may supply pre-packaged source tarballs for users. This can
|
||||
be done with the following commands:
|
||||
be done with the export.sh script in utils/release.
|
||||
|
||||
::
|
||||
|
||||
$ svn export https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/rc1 llvm-X.Yrc1
|
||||
$ svn export https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/rc1 clang-X.Yrc1
|
||||
$ svn export https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/rc1 dragonegg-X.Yrc1
|
||||
$ svn export https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/rc1 llvm-test-X.Yrc1
|
||||
$ ./export.sh -release X.Y.Z -rc $RC
|
||||
|
||||
$ tar -cvf - llvm-X.Yrc1 | gzip > llvm-X.Yrc1.src.tar.gz
|
||||
$ tar -cvf - clang-X.Yrc1 | gzip > clang-X.Yrc1.src.tar.gz
|
||||
$ tar -cvf - dragonegg-X.Yrc1 | gzip > dragonegg-X.Yrc1.src.tar.gz
|
||||
$ tar -cvf - llvm-test-X.Yrc1 | gzip > llvm-test-X.Yrc1.src.tar.gz
|
||||
This will generate source tarballs for each LLVM project being validated, which
|
||||
can be uploaded to the website for further testing.
|
||||
|
||||
Building the Release
|
||||
--------------------
|
||||
@ -384,21 +357,11 @@ mainline into the release branch.
|
||||
Tag the LLVM Final Release
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Tag the final release sources using the following procedure:
|
||||
Tag the final release sources using the tag.sh script in utils/release.
|
||||
|
||||
::
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/llvm/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/llvm/tags/RELEASE_XYZ/Final
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/cfe/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/cfe/tags/RELEASE_XYZ/Final
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/dragonegg/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/dragonegg/tags/RELEASE_XYZ/Final
|
||||
|
||||
$ svn copy https://llvm.org/svn/llvm-project/test-suite/branches/release_XY \
|
||||
https://llvm.org/svn/llvm-project/test-suite/tags/RELEASE_XYZ/Final
|
||||
$ ./tag.sh -release X.Y.Z -final
|
||||
|
||||
Update the LLVM Demo Page
|
||||
-------------------------
|
||||
|
1314
docs/LangRef.rst
1314
docs/LangRef.rst
File diff suppressed because it is too large
Load Diff
@ -112,7 +112,7 @@ Here we show how to use lib/Fuzzer on something real, yet simple: pcre2_::
|
||||
(cd pcre; ./autogen.sh; CC="clang -fsanitize=address $COV_FLAGS" ./configure --prefix=`pwd`/../inst && make -j && make install)
|
||||
# Build lib/Fuzzer files.
|
||||
clang -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
|
||||
# Build the the actual function that does something interesting with PCRE2.
|
||||
# Build the actual function that does something interesting with PCRE2.
|
||||
cat << EOF > pcre_fuzzer.cc
|
||||
#include <string.h>
|
||||
#include "pcre2posix.h"
|
||||
|
@ -60,26 +60,28 @@ to upload your patch):
|
||||
To upload a new patch:
|
||||
|
||||
* Click *Differential*.
|
||||
* Click *Create Diff*.
|
||||
* Paste the text diff or upload the patch file.
|
||||
Note that TODO
|
||||
* Click *+ Create Diff*.
|
||||
* Paste the text diff or browse to the patch file. Click *Create Diff*.
|
||||
* Leave the Repository field blank.
|
||||
* Leave the drop down on *Create a new Revision...* and click *Continue*.
|
||||
* Enter a descriptive title and summary. The title and summary are usually
|
||||
in the form of a :ref:`commit message <commit messages>`.
|
||||
* Add reviewers and mailing
|
||||
lists that you want to be included in the review. If your patch is
|
||||
for LLVM, add llvm-commits as a subscriber; if your patch is for Clang,
|
||||
for LLVM, add llvm-commits as a Subscriber; if your patch is for Clang,
|
||||
add cfe-commits.
|
||||
* Leave the Repository and Project fields blank.
|
||||
* Click *Save*.
|
||||
|
||||
To submit an updated patch:
|
||||
|
||||
* Click *Differential*.
|
||||
* Click *Create Diff*.
|
||||
* Paste the updated diff.
|
||||
* Click *+ Create Diff*.
|
||||
* Paste the updated diff or browse to the updated patch file. Click *Create Diff*.
|
||||
* Select the review you want to from the *Attach To* dropdown and click
|
||||
*Continue*.
|
||||
* Click *Save*.
|
||||
* Leave the Repository and Project fields blank.
|
||||
* Add comments about the changes in the new diff. Click *Save*.
|
||||
|
||||
Reviewing code with Phabricator
|
||||
-------------------------------
|
||||
@ -160,6 +162,6 @@ trivially a good fit for an official LLVM project.
|
||||
.. _LLVM's Phabricator: http://reviews.llvm.org
|
||||
.. _`http://reviews.llvm.org`: http://reviews.llvm.org
|
||||
.. _Code Repository Browser: http://reviews.llvm.org/diffusion/
|
||||
.. _Arcanist Quick Start: http://www.phabricator.com/docs/phabricator/article/Arcanist_Quick_Start.html
|
||||
.. _Arcanist User Guide: http://www.phabricator.com/docs/phabricator/article/Arcanist_User_Guide.html
|
||||
.. _Arcanist Quick Start: https://secure.phabricator.com/book/phabricator/article/arcanist_quick_start/
|
||||
.. _Arcanist User Guide: https://secure.phabricator.com/book/phabricator/article/arcanist/
|
||||
.. _llvm-reviews GitHub project: https://github.com/r4nt/llvm-reviews/
|
||||
|
@ -1868,7 +1868,7 @@ Iterating over predecessors & successors of blocks
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Iterating over the predecessors and successors of a block is quite easy with the
|
||||
routines defined in ``"llvm/Support/CFG.h"``. Just use code like this to
|
||||
routines defined in ``"llvm/IR/CFG.h"``. Just use code like this to
|
||||
iterate over all predecessors of BB:
|
||||
|
||||
.. code-block:: c++
|
||||
|
@ -1,12 +1,12 @@
|
||||
======================
|
||||
LLVM 3.7 Release Notes
|
||||
LLVM 3.8 Release Notes
|
||||
======================
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
.. warning::
|
||||
These are in-progress notes for the upcoming LLVM 3.7 release. You may
|
||||
These are in-progress notes for the upcoming LLVM 3.8 release. You may
|
||||
prefer the `LLVM 3.6 Release Notes <http://llvm.org/releases/3.6.0/docs
|
||||
/ReleaseNotes.html>`_.
|
||||
|
||||
@ -15,7 +15,7 @@ Introduction
|
||||
============
|
||||
|
||||
This document contains the release notes for the LLVM Compiler Infrastructure,
|
||||
release 3.7. Here we describe the status of LLVM, including major improvements
|
||||
release 3.8. Here we describe the status of LLVM, including major improvements
|
||||
from the previous release, improvements in various subprojects of LLVM, and
|
||||
some of the current users of the code. All LLVM releases may be downloaded
|
||||
from the `LLVM releases web site <http://llvm.org/releases/>`_.
|
||||
@ -41,18 +41,6 @@ Non-comprehensive list of changes in this release
|
||||
functionality, or simply have a lot to talk about), see the `NOTE` below
|
||||
for adding a new subsection.
|
||||
|
||||
* The minimum required Visual Studio version for building LLVM is now 2013
|
||||
Update 4.
|
||||
|
||||
* A new documentation page, :doc:`Frontend/PerformanceTips`, contains a
|
||||
collection of tips for frontend authors on how to generate IR which LLVM is
|
||||
able to effectively optimize.
|
||||
|
||||
* The DataLayout is no longer optional. All the IR level optimizations expects
|
||||
it to be present and the API has been changed to use a reference instead of
|
||||
a pointer to make it explicit. The Module owns the datalayout and it has to
|
||||
match the one attached to the TargetMachine for generating code.
|
||||
|
||||
* ... next change ...
|
||||
|
||||
.. NOTE
|
||||
@ -89,12 +77,12 @@ Changes to the OCaml bindings
|
||||
During this release ...
|
||||
|
||||
|
||||
External Open Source Projects Using LLVM 3.7
|
||||
External Open Source Projects Using LLVM 3.8
|
||||
============================================
|
||||
|
||||
An exciting aspect of LLVM is that it is used as an enabling technology for
|
||||
a lot of other language and tools projects. This section lists some of the
|
||||
projects that have already been updated to work with LLVM 3.7.
|
||||
projects that have already been updated to work with LLVM 3.8.
|
||||
|
||||
* A project
|
||||
|
||||
|
@ -221,12 +221,10 @@ lowered according to the calling convention specified at the
|
||||
intrinsic's callsite. Variants of the intrinsic with non-void return
|
||||
type also return a value according to calling convention.
|
||||
|
||||
On PowerPC, note that ``<target>`` must be the actual intended target of
|
||||
the indirect call. Specifically, even when compiling for the ELF V1 ABI,
|
||||
``<target>`` is not the function-descriptor address normally used as the C/C++
|
||||
function-pointer representation. As a result, the call target must be local
|
||||
because no adjustment or restoration of the TOC pointer (in register r2) will
|
||||
be performed.
|
||||
On PowerPC, note that ``<target>`` must be the ABI function pointer for the
|
||||
intended target of the indirect call. Specifically, when compiling for the
|
||||
ELF V1 ABI, ``<target>`` is the function-descriptor address normally used as
|
||||
the C/C++ function-pointer representation.
|
||||
|
||||
Requesting zero patch point arguments is valid. In this case, all
|
||||
variable operands are handled just like
|
||||
@ -501,3 +499,13 @@ the same requirement imposed by the llvm.gcroot intrinsic.) LLVM
|
||||
transformations must not substitute the alloca with any intervening
|
||||
value. This can be verified by the runtime simply by checking that the
|
||||
stack map's location is a Direct location type.
|
||||
|
||||
|
||||
Supported Architectures
|
||||
=======================
|
||||
|
||||
Support for StackMap generation and the related intrinsics requires
|
||||
some code for each backend. Today, only a subset of LLVM's backends
|
||||
are supported. The currently supported architectures are X86_64,
|
||||
PowerPC, and Aarch64.
|
||||
|
||||
|
@ -331,14 +331,16 @@ the user will patch over the 'num patch bytes' bytes of nops with a
|
||||
calling sequence specific to their runtime before executing the
|
||||
generated machine code. There are no guarantees with respect to the
|
||||
alignment of the nop sequence. Unlike :doc:`StackMaps` statepoints do
|
||||
not have a concept of shadow bytes.
|
||||
not have a concept of shadow bytes. Note that semantically the
|
||||
statepoint still represents a call or invoke to 'target', and the nop
|
||||
sequence after patching is expected to represent an operation
|
||||
equivalent to a call or invoke to 'target'.
|
||||
|
||||
The 'target' operand is the function actually being called. The
|
||||
target can be specified as either a symbolic LLVM function, or as an
|
||||
arbitrary Value of appropriate function type. Note that the function
|
||||
type must match the signature of the callee and the types of the 'call
|
||||
parameters' arguments. If 'num patch bytes' is non-zero then 'target'
|
||||
has to be the constant pointer null of the appropriate function type.
|
||||
parameters' arguments.
|
||||
|
||||
The '#call args' operand is the number of arguments to the actual
|
||||
call. It must exactly match the number of arguments passed in the
|
||||
@ -699,6 +701,12 @@ deoptimization or introspection) at safepoints. In that case, ask on the
|
||||
llvmdev mailing list for suggestions.
|
||||
|
||||
|
||||
Supported Architectures
|
||||
=======================
|
||||
|
||||
Support for statepoint generation requires some code for each backend.
|
||||
Today, only X86_64 is supported.
|
||||
|
||||
Bugs and Enhancements
|
||||
=====================
|
||||
|
||||
|
97
docs/_ocamldoc/style.css
Normal file
97
docs/_ocamldoc/style.css
Normal 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 }
|
@ -47,9 +47,9 @@ copyright = u'2003-2014, LLVM Project'
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '3.7'
|
||||
version = '3.8'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '3.7'
|
||||
release = '3.8'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -395,9 +395,8 @@ argument allocas in ``PrototypeAST::CreateArgumentAllocas``.
|
||||
DIScope *Scope = KSDbgInfo.LexicalBlocks.back();
|
||||
DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU.getFilename(),
|
||||
KSDbgInfo.TheCU.getDirectory());
|
||||
DILocalVariable D = DBuilder->createLocalVariable(
|
||||
dwarf::DW_TAG_arg_variable, Scope, Args[Idx], Unit, Line,
|
||||
KSDbgInfo.getDoubleTy(), Idx);
|
||||
DILocalVariable D = DBuilder->createParameterVariable(
|
||||
Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true);
|
||||
|
||||
Instruction *Call = DBuilder->insertDeclare(
|
||||
Alloca, D, DBuilder->createExpression(), Builder.GetInsertBlock());
|
||||
|
@ -65,6 +65,7 @@ Here's a simplified Kwalify_ schema with an extension to allow alternate types.
|
||||
, IMAGE_FILE_MACHINE_AMD64
|
||||
, IMAGE_FILE_MACHINE_ARM
|
||||
, IMAGE_FILE_MACHINE_ARMNT
|
||||
, IMAGE_FILE_MACHINE_ARM64
|
||||
, IMAGE_FILE_MACHINE_EBC
|
||||
, IMAGE_FILE_MACHINE_I386
|
||||
, IMAGE_FILE_MACHINE_IA64
|
||||
|
@ -560,7 +560,7 @@ void *MCJITHelper::getPointerToFunction(Function *F) {
|
||||
|
||||
// Set up the optimizer pipeline. Start with registering info about how the
|
||||
// target lays out data structures.
|
||||
OpenModule->setDataLayout(*NewEngine->getDataLayout());
|
||||
OpenModule->setDataLayout(NewEngine->getDataLayout());
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
FPM->add(createBasicAliasAnalysisPass());
|
||||
// Promote allocas to registers.
|
||||
|
@ -913,7 +913,7 @@ int main() {
|
||||
|
||||
// Set up the optimizer pipeline. Start with registering info about how the
|
||||
// target lays out data structures.
|
||||
TheModule->setDataLayout(*TheExecutionEngine->getDataLayout());
|
||||
TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
OurFPM.add(createBasicAliasAnalysisPass());
|
||||
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
||||
|
@ -1034,7 +1034,7 @@ int main() {
|
||||
|
||||
// Set up the optimizer pipeline. Start with registering info about how the
|
||||
// target lays out data structures.
|
||||
TheModule->setDataLayout(*TheExecutionEngine->getDataLayout());
|
||||
TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
OurFPM.add(createBasicAliasAnalysisPass());
|
||||
// Do simple "peephole" optimizations and bit-twiddling optzns.
|
||||
|
@ -1211,7 +1211,7 @@ int main() {
|
||||
|
||||
// Set up the optimizer pipeline. Start with registering info about how the
|
||||
// target lays out data structures.
|
||||
TheModule->setDataLayout(*TheExecutionEngine->getDataLayout());
|
||||
TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
OurFPM.add(createBasicAliasAnalysisPass());
|
||||
// Promote allocas to registers.
|
||||
|
@ -1253,9 +1253,8 @@ void PrototypeAST::CreateArgumentAllocas(Function *F) {
|
||||
DIScope *Scope = KSDbgInfo.LexicalBlocks.back();
|
||||
DIFile *Unit = DBuilder->createFile(KSDbgInfo.TheCU->getFilename(),
|
||||
KSDbgInfo.TheCU->getDirectory());
|
||||
DILocalVariable *D = DBuilder->createLocalVariable(
|
||||
dwarf::DW_TAG_arg_variable, Scope, Args[Idx], Unit, Line,
|
||||
KSDbgInfo.getDoubleTy(), Idx);
|
||||
DILocalVariable *D = DBuilder->createParameterVariable(
|
||||
Scope, Args[Idx], Idx + 1, Unit, Line, KSDbgInfo.getDoubleTy(), true);
|
||||
|
||||
DBuilder->insertDeclare(Alloca, D, DBuilder->createExpression(),
|
||||
DebugLoc::get(Line, 0, Scope),
|
||||
@ -1462,7 +1461,7 @@ int main() {
|
||||
|
||||
// Set up the optimizer pipeline. Start with registering info about how the
|
||||
// target lays out data structures.
|
||||
TheModule->setDataLayout(*TheExecutionEngine->getDataLayout());
|
||||
TheModule->setDataLayout(TheExecutionEngine->getDataLayout());
|
||||
#if 0
|
||||
// Provide basic AliasAnalysis support for GVN.
|
||||
OurFPM.add(createBasicAliasAnalysisPass());
|
||||
|
@ -717,7 +717,7 @@ public:
|
||||
M(new Module(GenerateUniqueName("jit_module_"),
|
||||
Session.getLLVMContext())),
|
||||
Builder(Session.getLLVMContext()) {
|
||||
M->setDataLayout(*Session.getTarget().getDataLayout());
|
||||
M->setDataLayout(Session.getTarget().createDataLayout());
|
||||
}
|
||||
|
||||
SessionContext& getSession() { return Session; }
|
||||
@ -1168,7 +1168,6 @@ public:
|
||||
|
||||
KaleidoscopeJIT(SessionContext &Session)
|
||||
: Session(Session),
|
||||
Mang(Session.getTarget().getDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())),
|
||||
LazyEmitLayer(CompileLayer),
|
||||
CompileCallbacks(LazyEmitLayer, CCMgrMemMgr, Session.getLLVMContext(),
|
||||
@ -1179,7 +1178,8 @@ public:
|
||||
std::string MangledName;
|
||||
{
|
||||
raw_string_ostream MangledNameStream(MangledName);
|
||||
Mang.getNameWithPrefix(MangledNameStream, Name);
|
||||
Mangler::getNameWithPrefix(MangledNameStream, Name,
|
||||
Session.getTarget().createDataLayout());
|
||||
}
|
||||
return MangledName;
|
||||
}
|
||||
@ -1306,7 +1306,6 @@ private:
|
||||
}
|
||||
|
||||
SessionContext &Session;
|
||||
Mangler Mang;
|
||||
SectionMemoryManager CCMgrMemMgr;
|
||||
ObjLayerT ObjectLayer;
|
||||
CompileLayerT CompileLayer;
|
||||
|
@ -716,7 +716,7 @@ public:
|
||||
M(new Module(GenerateUniqueName("jit_module_"),
|
||||
Session.getLLVMContext())),
|
||||
Builder(Session.getLLVMContext()) {
|
||||
M->setDataLayout(*Session.getTarget().getDataLayout());
|
||||
M->setDataLayout(Session.getTarget().createDataLayout());
|
||||
}
|
||||
|
||||
SessionContext& getSession() { return Session; }
|
||||
@ -1160,14 +1160,14 @@ public:
|
||||
typedef CompileLayerT::ModuleSetHandleT ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT(SessionContext &Session)
|
||||
: Mang(Session.getTarget().getDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {}
|
||||
: DL(Session.getTarget().createDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())) {}
|
||||
|
||||
std::string mangle(const std::string &Name) {
|
||||
std::string MangledName;
|
||||
{
|
||||
raw_string_ostream MangledNameStream(MangledName);
|
||||
Mang.getNameWithPrefix(MangledNameStream, Name);
|
||||
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
|
||||
}
|
||||
return MangledName;
|
||||
}
|
||||
@ -1201,8 +1201,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Mangler Mang;
|
||||
const DataLayout DL;
|
||||
ObjLayerT ObjectLayer;
|
||||
CompileLayerT CompileLayer;
|
||||
};
|
||||
|
@ -716,7 +716,7 @@ public:
|
||||
M(new Module(GenerateUniqueName("jit_module_"),
|
||||
Session.getLLVMContext())),
|
||||
Builder(Session.getLLVMContext()) {
|
||||
M->setDataLayout(*Session.getTarget().getDataLayout());
|
||||
M->setDataLayout(Session.getTarget().createDataLayout());
|
||||
}
|
||||
|
||||
SessionContext& getSession() { return Session; }
|
||||
@ -1162,15 +1162,15 @@ public:
|
||||
typedef LazyEmitLayerT::ModuleSetHandleT ModuleHandleT;
|
||||
|
||||
KaleidoscopeJIT(SessionContext &Session)
|
||||
: Mang(Session.getTarget().getDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())),
|
||||
LazyEmitLayer(CompileLayer) {}
|
||||
: DL(Session.getTarget().createDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())),
|
||||
LazyEmitLayer(CompileLayer) {}
|
||||
|
||||
std::string mangle(const std::string &Name) {
|
||||
std::string MangledName;
|
||||
{
|
||||
raw_string_ostream MangledNameStream(MangledName);
|
||||
Mang.getNameWithPrefix(MangledNameStream, Name);
|
||||
Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
|
||||
}
|
||||
return MangledName;
|
||||
}
|
||||
@ -1204,8 +1204,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Mangler Mang;
|
||||
const DataLayout DL;
|
||||
ObjLayerT ObjectLayer;
|
||||
CompileLayerT CompileLayer;
|
||||
LazyEmitLayerT LazyEmitLayer;
|
||||
|
@ -716,7 +716,7 @@ public:
|
||||
M(new Module(GenerateUniqueName("jit_module_"),
|
||||
Session.getLLVMContext())),
|
||||
Builder(Session.getLLVMContext()) {
|
||||
M->setDataLayout(*Session.getTarget().getDataLayout());
|
||||
M->setDataLayout(Session.getTarget().createDataLayout());
|
||||
}
|
||||
|
||||
SessionContext& getSession() { return Session; }
|
||||
@ -1162,7 +1162,6 @@ public:
|
||||
|
||||
KaleidoscopeJIT(SessionContext &Session)
|
||||
: Session(Session),
|
||||
Mang(Session.getTarget().getDataLayout()),
|
||||
CompileLayer(ObjectLayer, SimpleCompiler(Session.getTarget())),
|
||||
LazyEmitLayer(CompileLayer) {}
|
||||
|
||||
@ -1170,7 +1169,8 @@ public:
|
||||
std::string MangledName;
|
||||
{
|
||||
raw_string_ostream MangledNameStream(MangledName);
|
||||
Mang.getNameWithPrefix(MangledNameStream, Name);
|
||||
Mangler::getNameWithPrefix(MangledNameStream, Name,
|
||||
Session.getTarget().createDataLayout());
|
||||
}
|
||||
return MangledName;
|
||||
}
|
||||
@ -1236,7 +1236,6 @@ private:
|
||||
}
|
||||
|
||||
SessionContext &Session;
|
||||
Mangler Mang;
|
||||
ObjLayerT ObjectLayer;
|
||||
CompileLayerT CompileLayer;
|
||||
LazyEmitLayerT LazyEmitLayer;
|
||||
|
@ -161,15 +161,15 @@ typedef enum {
|
||||
/* FIXME: These attributes are currently not included in the C API as
|
||||
a temporary measure until the API/ABI impact to the C API is understood
|
||||
and the path forward agreed upon.
|
||||
LLVMAddressSafety = 1ULL << 32,
|
||||
LLVMStackProtectStrongAttribute = 1ULL<<33,
|
||||
LLVMCold = 1ULL << 34,
|
||||
LLVMOptimizeNone = 1ULL << 35,
|
||||
LLVMInAllocaAttribute = 1ULL << 36,
|
||||
LLVMNonNullAttribute = 1ULL << 37,
|
||||
LLVMJumpTableAttribute = 1ULL << 38,
|
||||
LLVMDereferenceableAttribute = 1ULL << 39,
|
||||
LLVMDereferenceableOrNullAttribute = 1ULL << 40,
|
||||
LLVMSanitizeAddressAttribute = 1ULL << 32,
|
||||
LLVMStackProtectStrongAttribute = 1ULL<<35,
|
||||
LLVMColdAttribute = 1ULL << 40,
|
||||
LLVMOptimizeNoneAttribute = 1ULL << 42,
|
||||
LLVMInAllocaAttribute = 1ULL << 43,
|
||||
LLVMNonNullAttribute = 1ULL << 44,
|
||||
LLVMJumpTableAttribute = 1ULL << 45,
|
||||
LLVMConvergentAttribute = 1ULL << 46,
|
||||
LLVMSafeStackAttribute = 1ULL << 47,
|
||||
*/
|
||||
} LLVMAttribute;
|
||||
|
||||
@ -248,7 +248,13 @@ typedef enum {
|
||||
|
||||
/* Exception Handling Operators */
|
||||
LLVMResume = 58,
|
||||
LLVMLandingPad = 59
|
||||
LLVMLandingPad = 59,
|
||||
LLVMCleanupRet = 61,
|
||||
LLVMCatchRet = 62,
|
||||
LLVMCatchPad = 63,
|
||||
LLVMTerminatePad = 64,
|
||||
LLVMCleanupPad = 65,
|
||||
LLVMCatchEndPad = 66
|
||||
|
||||
} LLVMOpcode;
|
||||
|
||||
@ -1203,6 +1209,7 @@ LLVMTypeRef LLVMX86MMXType(void);
|
||||
macro(InsertElementInst) \
|
||||
macro(InsertValueInst) \
|
||||
macro(LandingPadInst) \
|
||||
macro(CleanupPadInst) \
|
||||
macro(PHINode) \
|
||||
macro(SelectInst) \
|
||||
macro(ShuffleVectorInst) \
|
||||
@ -1215,6 +1222,11 @@ LLVMTypeRef LLVMX86MMXType(void);
|
||||
macro(SwitchInst) \
|
||||
macro(UnreachableInst) \
|
||||
macro(ResumeInst) \
|
||||
macro(CleanupReturnInst) \
|
||||
macro(CatchReturnInst) \
|
||||
macro(CatchPadInst) \
|
||||
macro(TerminatePadInst) \
|
||||
macro(CatchEndPadInst) \
|
||||
macro(UnaryInstruction) \
|
||||
macro(AllocaInst) \
|
||||
macro(CastInst) \
|
||||
@ -1887,6 +1899,20 @@ LLVMValueRef LLVMAddAlias(LLVMModuleRef M, LLVMTypeRef Ty, LLVMValueRef Aliasee,
|
||||
*/
|
||||
void LLVMDeleteFunction(LLVMValueRef Fn);
|
||||
|
||||
/**
|
||||
* Obtain the personality function attached to the function.
|
||||
*
|
||||
* @see llvm::Function::getPersonalityFn()
|
||||
*/
|
||||
LLVMValueRef LLVMGetPersonalityFn(LLVMValueRef Fn);
|
||||
|
||||
/**
|
||||
* Set the personality function attached to the function.
|
||||
*
|
||||
* @see llvm::Function::setPersonalityFn()
|
||||
*/
|
||||
void LLVMSetPersonalityFn(LLVMValueRef Fn, LLVMValueRef PersonalityFn);
|
||||
|
||||
/**
|
||||
* Obtain the ID number from a function instance.
|
||||
*
|
||||
@ -1936,7 +1962,7 @@ void LLVMSetGC(LLVMValueRef Fn, const char *Name);
|
||||
void LLVMAddFunctionAttr(LLVMValueRef Fn, LLVMAttribute PA);
|
||||
|
||||
/**
|
||||
* Add a target-dependent attribute to a fuction
|
||||
* Add a target-dependent attribute to a function
|
||||
* @see llvm::AttrBuilder::addAttribute()
|
||||
*/
|
||||
void LLVMAddTargetDependentFunctionAttr(LLVMValueRef Fn, const char *A,
|
||||
|
@ -81,7 +81,6 @@ uint64_t LLVMGetSymbolAddress(LLVMSymbolIteratorRef SI);
|
||||
uint64_t LLVMGetSymbolSize(LLVMSymbolIteratorRef SI);
|
||||
|
||||
// RelocationRef accessors
|
||||
uint64_t LLVMGetRelocationAddress(LLVMRelocationIteratorRef RI);
|
||||
uint64_t LLVMGetRelocationOffset(LLVMRelocationIteratorRef RI);
|
||||
LLVMSymbolIteratorRef LLVMGetRelocationSymbol(LLVMRelocationIteratorRef RI);
|
||||
uint64_t LLVMGetRelocationType(LLVMRelocationIteratorRef RI);
|
||||
|
@ -40,7 +40,7 @@ typedef bool lto_bool_t;
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define LTO_API_VERSION 15
|
||||
#define LTO_API_VERSION 17
|
||||
|
||||
/**
|
||||
* \since prior to LTO_API_VERSION=3
|
||||
@ -63,7 +63,8 @@ typedef enum {
|
||||
LTO_SYMBOL_SCOPE_PROTECTED = 0x00002000,
|
||||
LTO_SYMBOL_SCOPE_DEFAULT = 0x00001800,
|
||||
LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN = 0x00002800,
|
||||
LTO_SYMBOL_COMDAT = 0x00004000
|
||||
LTO_SYMBOL_COMDAT = 0x00004000,
|
||||
LTO_SYMBOL_ALIAS = 0x00008000
|
||||
} lto_symbol_attributes;
|
||||
|
||||
/**
|
||||
@ -280,39 +281,15 @@ lto_module_get_symbol_attribute(lto_module_t mod, unsigned int index);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of dependent libraries in the object module.
|
||||
* Returns the module's linker options.
|
||||
*
|
||||
* \since LTO_API_VERSION=8
|
||||
*/
|
||||
extern unsigned int
|
||||
lto_module_get_num_deplibs(lto_module_t mod);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ith dependent library in the module.
|
||||
* The linker options may consist of multiple flags. It is the linker's
|
||||
* responsibility to split the flags using a platform-specific mechanism.
|
||||
*
|
||||
* \since LTO_API_VERSION=8
|
||||
* \since LTO_API_VERSION=16
|
||||
*/
|
||||
extern const char*
|
||||
lto_module_get_deplib(lto_module_t mod, unsigned int index);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the number of linker options in the object module.
|
||||
*
|
||||
* \since LTO_API_VERSION=8
|
||||
*/
|
||||
extern unsigned int
|
||||
lto_module_get_num_linkeropts(lto_module_t mod);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ith linker option in the module.
|
||||
*
|
||||
* \since LTO_API_VERSION=8
|
||||
*/
|
||||
extern const char*
|
||||
lto_module_get_linkeropt(lto_module_t mod, unsigned int index);
|
||||
lto_module_get_linkeropts(lto_module_t mod);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -276,6 +276,10 @@ public:
|
||||
/// \param isIEEE - If 128 bit number, select between PPC and IEEE
|
||||
static APFloat getAllOnesValue(unsigned BitWidth, bool isIEEE = false);
|
||||
|
||||
/// Returns the size of the floating point number (in bits) in the given
|
||||
/// semantics.
|
||||
static unsigned getSizeInBits(const fltSemantics &Sem);
|
||||
|
||||
/// @}
|
||||
|
||||
/// Used to insert APFloat objects, or objects that contain APFloat objects,
|
||||
|
@ -1038,7 +1038,9 @@ public:
|
||||
/// the validity of the less-than relationship.
|
||||
///
|
||||
/// \returns true if *this < RHS when considered unsigned.
|
||||
bool ult(uint64_t RHS) const { return ult(APInt(getBitWidth(), RHS)); }
|
||||
bool ult(uint64_t RHS) const {
|
||||
return getActiveBits() > 64 ? false : getZExtValue() < RHS;
|
||||
}
|
||||
|
||||
/// \brief Signed less than comparison
|
||||
///
|
||||
@ -1054,7 +1056,9 @@ public:
|
||||
/// the validity of the less-than relationship.
|
||||
///
|
||||
/// \returns true if *this < RHS when considered signed.
|
||||
bool slt(uint64_t RHS) const { return slt(APInt(getBitWidth(), RHS)); }
|
||||
bool slt(int64_t RHS) const {
|
||||
return getMinSignedBits() > 64 ? isNegative() : getSExtValue() < RHS;
|
||||
}
|
||||
|
||||
/// \brief Unsigned less or equal comparison
|
||||
///
|
||||
@ -1070,7 +1074,7 @@ public:
|
||||
/// the validity of the less-or-equal relationship.
|
||||
///
|
||||
/// \returns true if *this <= RHS when considered unsigned.
|
||||
bool ule(uint64_t RHS) const { return ule(APInt(getBitWidth(), RHS)); }
|
||||
bool ule(uint64_t RHS) const { return !ugt(RHS); }
|
||||
|
||||
/// \brief Signed less or equal comparison
|
||||
///
|
||||
@ -1086,7 +1090,7 @@ public:
|
||||
/// validity of the less-or-equal relationship.
|
||||
///
|
||||
/// \returns true if *this <= RHS when considered signed.
|
||||
bool sle(uint64_t RHS) const { return sle(APInt(getBitWidth(), RHS)); }
|
||||
bool sle(uint64_t RHS) const { return !sgt(RHS); }
|
||||
|
||||
/// \brief Unsigned greather than comparison
|
||||
///
|
||||
@ -1102,7 +1106,9 @@ public:
|
||||
/// the validity of the greater-than relationship.
|
||||
///
|
||||
/// \returns true if *this > RHS when considered unsigned.
|
||||
bool ugt(uint64_t RHS) const { return ugt(APInt(getBitWidth(), RHS)); }
|
||||
bool ugt(uint64_t RHS) const {
|
||||
return getActiveBits() > 64 ? true : getZExtValue() > RHS;
|
||||
}
|
||||
|
||||
/// \brief Signed greather than comparison
|
||||
///
|
||||
@ -1118,7 +1124,9 @@ public:
|
||||
/// the validity of the greater-than relationship.
|
||||
///
|
||||
/// \returns true if *this > RHS when considered signed.
|
||||
bool sgt(uint64_t RHS) const { return sgt(APInt(getBitWidth(), RHS)); }
|
||||
bool sgt(int64_t RHS) const {
|
||||
return getMinSignedBits() > 64 ? !isNegative() : getSExtValue() > RHS;
|
||||
}
|
||||
|
||||
/// \brief Unsigned greater or equal comparison
|
||||
///
|
||||
@ -1134,7 +1142,7 @@ public:
|
||||
/// the validity of the greater-or-equal relationship.
|
||||
///
|
||||
/// \returns true if *this >= RHS when considered unsigned.
|
||||
bool uge(uint64_t RHS) const { return uge(APInt(getBitWidth(), RHS)); }
|
||||
bool uge(uint64_t RHS) const { return !ult(RHS); }
|
||||
|
||||
/// \brief Signed greather or equal comparison
|
||||
///
|
||||
@ -1150,7 +1158,7 @@ public:
|
||||
/// the validity of the greater-or-equal relationship.
|
||||
///
|
||||
/// \returns true if *this >= RHS when considered signed.
|
||||
bool sge(uint64_t RHS) const { return sge(APInt(getBitWidth(), RHS)); }
|
||||
bool sge(int64_t RHS) const { return !slt(RHS); }
|
||||
|
||||
/// This operation tests if there are any pairs of corresponding bits
|
||||
/// between this APInt and RHS that are both set.
|
||||
|
@ -33,6 +33,15 @@ public:
|
||||
explicit APSInt(APInt I, bool isUnsigned = true)
|
||||
: APInt(std::move(I)), IsUnsigned(isUnsigned) {}
|
||||
|
||||
/// Construct an APSInt from a string representation.
|
||||
///
|
||||
/// This constructor interprets the string \p Str using the radix of 10.
|
||||
/// The interpretation stops at the end of the string. The bit width of the
|
||||
/// constructed APSInt is determined automatically.
|
||||
///
|
||||
/// \param Str the string to be interpreted.
|
||||
explicit APSInt(StringRef Str);
|
||||
|
||||
APSInt &operator=(APInt RHS) {
|
||||
// Retain our current sign.
|
||||
APInt::operator=(std::move(RHS));
|
||||
|
@ -85,7 +85,7 @@ namespace llvm {
|
||||
|
||||
/// Construct an ArrayRef from a std::initializer_list.
|
||||
/*implicit*/ ArrayRef(const std::initializer_list<T> &Vec)
|
||||
: Data(Vec.begin() == Vec.end() ? (T*)0 : Vec.begin()),
|
||||
: Data(Vec.begin() == Vec.end() ? (T*)nullptr : Vec.begin()),
|
||||
Length(Vec.size()) {}
|
||||
|
||||
/// Construct an ArrayRef<const T*> from ArrayRef<T*>. This uses SFINAE to
|
||||
@ -286,6 +286,11 @@ namespace llvm {
|
||||
return MutableArrayRef<T>(data()+N, M);
|
||||
}
|
||||
|
||||
MutableArrayRef<T> drop_back(unsigned N) const {
|
||||
assert(this->size() >= N && "Dropping more elements than exist");
|
||||
return slice(0, this->size() - N);
|
||||
}
|
||||
|
||||
/// @}
|
||||
/// @name Operator Overloads
|
||||
/// @{
|
||||
|
@ -14,6 +14,8 @@
|
||||
#ifndef LLVM_ADT_DENSEMAPINFO_H
|
||||
#define LLVM_ADT_DENSEMAPINFO_H
|
||||
|
||||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/PointerLikeTypeTraits.h"
|
||||
#include "llvm/Support/type_traits.h"
|
||||
|
||||
@ -163,6 +165,31 @@ struct DenseMapInfo<std::pair<T, U> > {
|
||||
}
|
||||
};
|
||||
|
||||
// Provide DenseMapInfo for StringRefs.
|
||||
template <> struct DenseMapInfo<StringRef> {
|
||||
static inline StringRef getEmptyKey() {
|
||||
return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(0)),
|
||||
0);
|
||||
}
|
||||
static inline StringRef getTombstoneKey() {
|
||||
return StringRef(reinterpret_cast<const char *>(~static_cast<uintptr_t>(1)),
|
||||
0);
|
||||
}
|
||||
static unsigned getHashValue(StringRef Val) {
|
||||
assert(Val.data() != getEmptyKey().data() && "Cannot hash the empty key!");
|
||||
assert(Val.data() != getTombstoneKey().data() &&
|
||||
"Cannot hash the tombstone key!");
|
||||
return (unsigned)(hash_value(Val));
|
||||
}
|
||||
static bool isEqual(StringRef LHS, StringRef RHS) {
|
||||
if (RHS.data() == getEmptyKey().data())
|
||||
return LHS.data() == getEmptyKey().data();
|
||||
if (RHS.data() == getTombstoneKey().data())
|
||||
return LHS.data() == getTombstoneKey().data();
|
||||
return LHS == RHS;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -196,6 +196,41 @@ inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) {
|
||||
return mapped_iterator<ItTy, FuncTy>(I, F);
|
||||
}
|
||||
|
||||
/// \brief Metafunction to determine if type T has a member called rbegin().
|
||||
template <typename T> struct has_rbegin {
|
||||
template <typename U> static char(&f(const U &, decltype(&U::rbegin)))[1];
|
||||
static char(&f(...))[2];
|
||||
const static bool value = sizeof(f(std::declval<T>(), nullptr)) == 1;
|
||||
};
|
||||
|
||||
// Returns an iterator_range over the given container which iterates in reverse.
|
||||
// Note that the container must have rbegin()/rend() methods for this to work.
|
||||
template <typename ContainerTy>
|
||||
auto reverse(ContainerTy &&C,
|
||||
typename std::enable_if<has_rbegin<ContainerTy>::value>::type * =
|
||||
nullptr) -> decltype(make_range(C.rbegin(), C.rend())) {
|
||||
return make_range(C.rbegin(), C.rend());
|
||||
}
|
||||
|
||||
// Returns a std::reverse_iterator wrapped around the given iterator.
|
||||
template <typename IteratorTy>
|
||||
std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) {
|
||||
return std::reverse_iterator<IteratorTy>(It);
|
||||
}
|
||||
|
||||
// Returns an iterator_range over the given container which iterates in reverse.
|
||||
// Note that the container must have begin()/end() methods which return
|
||||
// bidirectional iterators for this to work.
|
||||
template <typename ContainerTy>
|
||||
auto reverse(
|
||||
ContainerTy &&C,
|
||||
typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr)
|
||||
-> decltype(make_range(llvm::make_reverse_iterator(std::end(C)),
|
||||
llvm::make_reverse_iterator(std::begin(C)))) {
|
||||
return make_range(llvm::make_reverse_iterator(std::end(C)),
|
||||
llvm::make_reverse_iterator(std::begin(C)));
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Extra additions to <utility>
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -44,6 +44,8 @@ public:
|
||||
typedef Vector vector_type;
|
||||
typedef typename vector_type::const_iterator iterator;
|
||||
typedef typename vector_type::const_iterator const_iterator;
|
||||
typedef typename vector_type::const_reverse_iterator reverse_iterator;
|
||||
typedef typename vector_type::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename vector_type::size_type size_type;
|
||||
|
||||
/// \brief Construct an empty SetVector
|
||||
@ -85,6 +87,26 @@ public:
|
||||
return vector_.end();
|
||||
}
|
||||
|
||||
/// \brief Get an reverse_iterator to the end of the SetVector.
|
||||
reverse_iterator rbegin() {
|
||||
return vector_.rbegin();
|
||||
}
|
||||
|
||||
/// \brief Get a const_reverse_iterator to the end of the SetVector.
|
||||
const_reverse_iterator rbegin() const {
|
||||
return vector_.rbegin();
|
||||
}
|
||||
|
||||
/// \brief Get a reverse_iterator to the beginning of the SetVector.
|
||||
reverse_iterator rend() {
|
||||
return vector_.rend();
|
||||
}
|
||||
|
||||
/// \brief Get a const_reverse_iterator to the beginning of the SetVector.
|
||||
const_reverse_iterator rend() const {
|
||||
return vector_.rend();
|
||||
}
|
||||
|
||||
/// \brief Return the last element of the SetVector.
|
||||
const T &back() const {
|
||||
assert(!empty() && "Cannot call back() on empty SetVector!");
|
||||
|
@ -453,6 +453,9 @@ public:
|
||||
|
||||
// Assignment
|
||||
SparseBitVector& operator=(const SparseBitVector& RHS) {
|
||||
if (this == &RHS)
|
||||
return *this;
|
||||
|
||||
Elements.clear();
|
||||
|
||||
ElementListConstIter ElementIter = RHS.Elements.begin();
|
||||
@ -559,6 +562,9 @@ public:
|
||||
|
||||
// Union our bitmap with the RHS and return true if we changed.
|
||||
bool operator|=(const SparseBitVector &RHS) {
|
||||
if (this == &RHS)
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
ElementListIter Iter1 = Elements.begin();
|
||||
ElementListConstIter Iter2 = RHS.Elements.begin();
|
||||
@ -587,6 +593,9 @@ public:
|
||||
|
||||
// Intersect our bitmap with the RHS and return true if ours changed.
|
||||
bool operator&=(const SparseBitVector &RHS) {
|
||||
if (this == &RHS)
|
||||
return false;
|
||||
|
||||
bool changed = false;
|
||||
ElementListIter Iter1 = Elements.begin();
|
||||
ElementListConstIter Iter2 = RHS.Elements.begin();
|
||||
@ -619,9 +628,13 @@ public:
|
||||
ElementListIter IterTmp = Iter1;
|
||||
++Iter1;
|
||||
Elements.erase(IterTmp);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
Elements.erase(Iter1, Elements.end());
|
||||
if (Iter1 != Elements.end()) {
|
||||
Elements.erase(Iter1, Elements.end());
|
||||
changed = true;
|
||||
}
|
||||
CurrElementIter = Elements.begin();
|
||||
return changed;
|
||||
}
|
||||
@ -629,6 +642,14 @@ public:
|
||||
// Intersect our bitmap with the complement of the RHS and return true
|
||||
// if ours changed.
|
||||
bool intersectWithComplement(const SparseBitVector &RHS) {
|
||||
if (this == &RHS) {
|
||||
if (!empty()) {
|
||||
clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool changed = false;
|
||||
ElementListIter Iter1 = Elements.begin();
|
||||
ElementListConstIter Iter2 = RHS.Elements.begin();
|
||||
@ -675,6 +696,15 @@ public:
|
||||
void intersectWithComplement(const SparseBitVector<ElementSize> &RHS1,
|
||||
const SparseBitVector<ElementSize> &RHS2)
|
||||
{
|
||||
if (this == &RHS1) {
|
||||
intersectWithComplement(RHS2);
|
||||
return;
|
||||
} else if (this == &RHS2) {
|
||||
SparseBitVector RHS2Copy(RHS2);
|
||||
intersectWithComplement(RHS1, RHS2Copy);
|
||||
return;
|
||||
}
|
||||
|
||||
Elements.clear();
|
||||
CurrElementIter = Elements.begin();
|
||||
ElementListConstIter Iter1 = RHS1.Elements.begin();
|
||||
|
@ -85,7 +85,9 @@ public:
|
||||
spir64, // SPIR: standard portable IR for OpenCL 64-bit version
|
||||
kalimba, // Kalimba: generic kalimba
|
||||
shave, // SHAVE: Movidius vector VLIW processors
|
||||
LastArchType = shave
|
||||
wasm32, // WebAssembly with 32-bit pointers
|
||||
wasm64, // WebAssembly with 64-bit pointers
|
||||
LastArchType = wasm64
|
||||
};
|
||||
enum SubArchType {
|
||||
NoSubArch,
|
||||
@ -168,7 +170,8 @@ public:
|
||||
MSVC,
|
||||
Itanium,
|
||||
Cygnus,
|
||||
LastEnvironmentType = Cygnus
|
||||
AMDOpenCL,
|
||||
LastEnvironmentType = AMDOpenCL
|
||||
};
|
||||
enum ObjectFormatType {
|
||||
UnknownObjectFormat,
|
||||
@ -567,6 +570,22 @@ public:
|
||||
/// architecture if no such variant can be found.
|
||||
llvm::Triple get64BitArchVariant() const;
|
||||
|
||||
/// Form a triple with a big endian variant of the current architecture.
|
||||
///
|
||||
/// This can be used to move across "families" of architectures where useful.
|
||||
///
|
||||
/// \returns A new triple with a big endian architecture or an unknown
|
||||
/// architecture if no such variant can be found.
|
||||
llvm::Triple getBigEndianArchVariant() const;
|
||||
|
||||
/// Form a triple with a little endian variant of the current architecture.
|
||||
///
|
||||
/// This can be used to move across "families" of architectures where useful.
|
||||
///
|
||||
/// \returns A new triple with a little endian architecture or an unknown
|
||||
/// architecture if no such variant can be found.
|
||||
llvm::Triple getLittleEndianArchVariant() const;
|
||||
|
||||
/// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting.
|
||||
///
|
||||
/// \param Arch the architecture name (e.g., "armv7s"). If it is an empty
|
||||
|
@ -50,50 +50,51 @@ unsigned ComputeEditDistance(ArrayRef<T> FromArray, ArrayRef<T> ToArray,
|
||||
// http://en.wikipedia.org/wiki/Levenshtein_distance
|
||||
//
|
||||
// Although the algorithm is typically described using an m x n
|
||||
// array, only two rows are used at a time, so this implementation
|
||||
// just keeps two separate vectors for those two rows.
|
||||
// array, only one row plus one element are used at a time, so this
|
||||
// implementation just keeps one vector for the row. To update one entry,
|
||||
// only the entries to the left, top, and top-left are needed. The left
|
||||
// entry is in Row[x-1], the top entry is what's in Row[x] from the last
|
||||
// iteration, and the top-left entry is stored in Previous.
|
||||
typename ArrayRef<T>::size_type m = FromArray.size();
|
||||
typename ArrayRef<T>::size_type n = ToArray.size();
|
||||
|
||||
const unsigned SmallBufferSize = 64;
|
||||
unsigned SmallBuffer[SmallBufferSize];
|
||||
std::unique_ptr<unsigned[]> Allocated;
|
||||
unsigned *Previous = SmallBuffer;
|
||||
if (2*(n + 1) > SmallBufferSize) {
|
||||
Previous = new unsigned [2*(n+1)];
|
||||
Allocated.reset(Previous);
|
||||
unsigned *Row = SmallBuffer;
|
||||
if (n + 1 > SmallBufferSize) {
|
||||
Row = new unsigned[n + 1];
|
||||
Allocated.reset(Row);
|
||||
}
|
||||
unsigned *Current = Previous + (n + 1);
|
||||
|
||||
for (unsigned i = 0; i <= n; ++i)
|
||||
Previous[i] = i;
|
||||
for (unsigned i = 1; i <= n; ++i)
|
||||
Row[i] = i;
|
||||
|
||||
for (typename ArrayRef<T>::size_type y = 1; y <= m; ++y) {
|
||||
Current[0] = y;
|
||||
unsigned BestThisRow = Current[0];
|
||||
Row[0] = y;
|
||||
unsigned BestThisRow = Row[0];
|
||||
|
||||
unsigned Previous = y - 1;
|
||||
for (typename ArrayRef<T>::size_type x = 1; x <= n; ++x) {
|
||||
int OldRow = Row[x];
|
||||
if (AllowReplacements) {
|
||||
Current[x] = std::min(
|
||||
Previous[x-1] + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
|
||||
std::min(Current[x-1], Previous[x])+1);
|
||||
Row[x] = std::min(
|
||||
Previous + (FromArray[y-1] == ToArray[x-1] ? 0u : 1u),
|
||||
std::min(Row[x-1], Row[x])+1);
|
||||
}
|
||||
else {
|
||||
if (FromArray[y-1] == ToArray[x-1]) Current[x] = Previous[x-1];
|
||||
else Current[x] = std::min(Current[x-1], Previous[x]) + 1;
|
||||
if (FromArray[y-1] == ToArray[x-1]) Row[x] = Previous;
|
||||
else Row[x] = std::min(Row[x-1], Row[x]) + 1;
|
||||
}
|
||||
BestThisRow = std::min(BestThisRow, Current[x]);
|
||||
Previous = OldRow;
|
||||
BestThisRow = std::min(BestThisRow, Row[x]);
|
||||
}
|
||||
|
||||
if (MaxEditDistance && BestThisRow > MaxEditDistance)
|
||||
return MaxEditDistance + 1;
|
||||
|
||||
unsigned *tmp = Current;
|
||||
Current = Previous;
|
||||
Previous = tmp;
|
||||
}
|
||||
|
||||
unsigned Result = Previous[n];
|
||||
unsigned Result = Row[n];
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
@ -162,6 +162,8 @@ protected:
|
||||
int>::type = 0)
|
||||
: I(std::forward<U &&>(u)) {}
|
||||
|
||||
const WrappedIteratorT &wrapped() const { return I; }
|
||||
|
||||
public:
|
||||
typedef DifferenceTypeT difference_type;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define LLVM_ADT_ITERATOR_RANGE_H
|
||||
|
||||
#include <utility>
|
||||
#include <iterator>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
@ -32,6 +33,12 @@ class iterator_range {
|
||||
IteratorT begin_iterator, end_iterator;
|
||||
|
||||
public:
|
||||
//TODO: Add SFINAE to test that the Container's iterators match the range's
|
||||
// iterators.
|
||||
template <typename Container>
|
||||
iterator_range(Container &&c)
|
||||
//TODO: Consider ADL/non-member begin/end calls.
|
||||
: begin_iterator(c.begin()), end_iterator(c.end()) {}
|
||||
iterator_range(IteratorT begin_iterator, IteratorT end_iterator)
|
||||
: begin_iterator(std::move(begin_iterator)),
|
||||
end_iterator(std::move(end_iterator)) {}
|
||||
@ -51,6 +58,11 @@ template <class T> iterator_range<T> make_range(T x, T y) {
|
||||
template <typename T> iterator_range<T> make_range(std::pair<T, T> p) {
|
||||
return iterator_range<T>(std::move(p.first), std::move(p.second));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
iterator_range<decltype(begin(std::declval<T>()))> drop_begin(T &&t, int n) {
|
||||
return make_range(std::next(begin(t), n), end(t));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -16,11 +16,12 @@
|
||||
// which automatically provides functionality for the entire suite of client
|
||||
// APIs.
|
||||
//
|
||||
// This API identifies memory regions with the Location class. The pointer
|
||||
// This API identifies memory regions with the MemoryLocation class. The pointer
|
||||
// component specifies the base memory address of the region. The Size specifies
|
||||
// the maximum size (in address units) of the memory region, or UnknownSize if
|
||||
// the size is not known. The TBAA tag identifies the "type" of the memory
|
||||
// reference; see the TypeBasedAliasAnalysis class for details.
|
||||
// the maximum size (in address units) of the memory region, or
|
||||
// MemoryLocation::UnknownSize if the size is not known. The TBAA tag
|
||||
// identifies the "type" of the memory reference; see the
|
||||
// TypeBasedAliasAnalysis class for details.
|
||||
//
|
||||
// Some non-obvious details include:
|
||||
// - Pointers that point to two completely different objects in memory never
|
||||
@ -54,6 +55,106 @@ class AnalysisUsage;
|
||||
class MemTransferInst;
|
||||
class MemIntrinsic;
|
||||
class DominatorTree;
|
||||
class OrderedBasicBlock;
|
||||
|
||||
/// The possible results of an alias query.
|
||||
///
|
||||
/// These results are always computed between two MemoryLocation objects as
|
||||
/// a query to some alias analysis.
|
||||
///
|
||||
/// Note that these are unscoped enumerations because we would like to support
|
||||
/// implicitly testing a result for the existence of any possible aliasing with
|
||||
/// a conversion to bool, but an "enum class" doesn't support this. The
|
||||
/// canonical names from the literature are suffixed and unique anyways, and so
|
||||
/// they serve as global constants in LLVM for these results.
|
||||
///
|
||||
/// See docs/AliasAnalysis.html for more information on the specific meanings
|
||||
/// of these values.
|
||||
enum AliasResult {
|
||||
/// The two locations do not alias at all.
|
||||
///
|
||||
/// This value is arranged to convert to false, while all other values
|
||||
/// convert to true. This allows a boolean context to convert the result to
|
||||
/// a binary flag indicating whether there is the possibility of aliasing.
|
||||
NoAlias = 0,
|
||||
/// The two locations may or may not alias. This is the least precise result.
|
||||
MayAlias,
|
||||
/// The two locations alias, but only due to a partial overlap.
|
||||
PartialAlias,
|
||||
/// The two locations precisely alias each other.
|
||||
MustAlias,
|
||||
};
|
||||
|
||||
/// Flags indicating whether a memory access modifies or references memory.
|
||||
///
|
||||
/// This is no access at all, a modification, a reference, or both
|
||||
/// a modification and a reference. These are specifically structured such that
|
||||
/// they form a two bit matrix and bit-tests for 'mod' or 'ref' work with any
|
||||
/// of the possible values.
|
||||
enum ModRefInfo {
|
||||
/// The access neither references nor modifies the value stored in memory.
|
||||
MRI_NoModRef = 0,
|
||||
/// The access references the value stored in memory.
|
||||
MRI_Ref = 1,
|
||||
/// The access modifies the value stored in memory.
|
||||
MRI_Mod = 2,
|
||||
/// The access both references and modifies the value stored in memory.
|
||||
MRI_ModRef = MRI_Ref | MRI_Mod
|
||||
};
|
||||
|
||||
/// The locations at which a function might access memory.
|
||||
///
|
||||
/// These are primarily used in conjunction with the \c AccessKind bits to
|
||||
/// describe both the nature of access and the locations of access for a
|
||||
/// function call.
|
||||
enum FunctionModRefLocation {
|
||||
/// Base case is no access to memory.
|
||||
FMRL_Nowhere = 0,
|
||||
/// Access to memory via argument pointers.
|
||||
FMRL_ArgumentPointees = 4,
|
||||
/// Access to any memory.
|
||||
FMRL_Anywhere = 8 | FMRL_ArgumentPointees
|
||||
};
|
||||
|
||||
/// Summary of how a function affects memory in the program.
|
||||
///
|
||||
/// Loads from constant globals are not considered memory accesses for this
|
||||
/// interface. Also, functions may freely modify stack space local to their
|
||||
/// invocation without having to report it through these interfaces.
|
||||
enum FunctionModRefBehavior {
|
||||
/// This function does not perform any non-local loads or stores to memory.
|
||||
///
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readnone' attribute.
|
||||
/// This property corresponds to the IntrNoMem LLVM intrinsic flag.
|
||||
FMRB_DoesNotAccessMemory = FMRL_Nowhere | MRI_NoModRef,
|
||||
|
||||
/// The only memory references in this function (if it has any) are
|
||||
/// non-volatile loads from objects pointed to by its pointer-typed
|
||||
/// arguments, with arbitrary offsets.
|
||||
///
|
||||
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
|
||||
FMRB_OnlyReadsArgumentPointees = FMRL_ArgumentPointees | MRI_Ref,
|
||||
|
||||
/// The only memory references in this function (if it has any) are
|
||||
/// non-volatile loads and stores from objects pointed to by its
|
||||
/// pointer-typed arguments, with arbitrary offsets.
|
||||
///
|
||||
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
|
||||
FMRB_OnlyAccessesArgumentPointees = FMRL_ArgumentPointees | MRI_ModRef,
|
||||
|
||||
/// This function does not perform any non-local stores or volatile loads,
|
||||
/// but may read from any memory location.
|
||||
///
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readonly' attribute.
|
||||
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
|
||||
FMRB_OnlyReadsMemory = FMRL_Anywhere | MRI_Ref,
|
||||
|
||||
/// This indicates that the function could not be classified into one of the
|
||||
/// behaviors above.
|
||||
FMRB_UnknownModRefBehavior = FMRL_Anywhere | MRI_ModRef
|
||||
};
|
||||
|
||||
class AliasAnalysis {
|
||||
protected:
|
||||
@ -80,11 +181,6 @@ public:
|
||||
AliasAnalysis() : DL(nullptr), TLI(nullptr), AA(nullptr) {}
|
||||
virtual ~AliasAnalysis(); // We want to be subclassed
|
||||
|
||||
/// UnknownSize - This is a special value which can be used with the
|
||||
/// size arguments in alias queries to indicate that the caller does not
|
||||
/// know the sizes of the potential memory references.
|
||||
static uint64_t const UnknownSize = MemoryLocation::UnknownSize;
|
||||
|
||||
/// getTargetLibraryInfo - Return a pointer to the current TargetLibraryInfo
|
||||
/// object, or null if no TargetLibraryInfo object is available.
|
||||
///
|
||||
@ -96,242 +192,284 @@ public:
|
||||
uint64_t getTypeStoreSize(Type *Ty);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Alias Queries...
|
||||
///
|
||||
/// \name Alias Queries
|
||||
/// @{
|
||||
|
||||
/// Legacy typedef for the AA location object. New code should use \c
|
||||
/// MemoryLocation directly.
|
||||
typedef MemoryLocation Location;
|
||||
|
||||
/// Alias analysis result - Either we know for sure that it does not alias, we
|
||||
/// know for sure it must alias, or we don't know anything: The two pointers
|
||||
/// _might_ alias. This enum is designed so you can do things like:
|
||||
/// if (AA.alias(P1, P2)) { ... }
|
||||
/// to check to see if two pointers might alias.
|
||||
///
|
||||
/// See docs/AliasAnalysis.html for more information on the specific meanings
|
||||
/// of these values.
|
||||
///
|
||||
enum AliasResult {
|
||||
NoAlias = 0, ///< No dependencies.
|
||||
MayAlias, ///< Anything goes.
|
||||
PartialAlias, ///< Pointers differ, but pointees overlap.
|
||||
MustAlias ///< Pointers are equal.
|
||||
};
|
||||
|
||||
/// alias - The main low level interface to the alias analysis implementation.
|
||||
/// The main low level interface to the alias analysis implementation.
|
||||
/// Returns an AliasResult indicating whether the two pointers are aliased to
|
||||
/// each other. This is the interface that must be implemented by specific
|
||||
/// each other. This is the interface that must be implemented by specific
|
||||
/// alias analysis implementations.
|
||||
virtual AliasResult alias(const Location &LocA, const Location &LocB);
|
||||
virtual AliasResult alias(const MemoryLocation &LocA,
|
||||
const MemoryLocation &LocB);
|
||||
|
||||
/// alias - A convenience wrapper.
|
||||
AliasResult alias(const Value *V1, uint64_t V1Size,
|
||||
const Value *V2, uint64_t V2Size) {
|
||||
return alias(Location(V1, V1Size), Location(V2, V2Size));
|
||||
/// A convenience wrapper around the primary \c alias interface.
|
||||
AliasResult alias(const Value *V1, uint64_t V1Size, const Value *V2,
|
||||
uint64_t V2Size) {
|
||||
return alias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size));
|
||||
}
|
||||
|
||||
/// alias - A convenience wrapper.
|
||||
/// A convenience wrapper around the primary \c alias interface.
|
||||
AliasResult alias(const Value *V1, const Value *V2) {
|
||||
return alias(V1, UnknownSize, V2, UnknownSize);
|
||||
return alias(V1, MemoryLocation::UnknownSize, V2,
|
||||
MemoryLocation::UnknownSize);
|
||||
}
|
||||
|
||||
/// isNoAlias - A trivial helper function to check to see if the specified
|
||||
/// pointers are no-alias.
|
||||
bool isNoAlias(const Location &LocA, const Location &LocB) {
|
||||
/// A trivial helper function to check to see if the specified pointers are
|
||||
/// no-alias.
|
||||
bool isNoAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
|
||||
return alias(LocA, LocB) == NoAlias;
|
||||
}
|
||||
|
||||
/// isNoAlias - A convenience wrapper.
|
||||
bool isNoAlias(const Value *V1, uint64_t V1Size,
|
||||
const Value *V2, uint64_t V2Size) {
|
||||
return isNoAlias(Location(V1, V1Size), Location(V2, V2Size));
|
||||
/// A convenience wrapper around the \c isNoAlias helper interface.
|
||||
bool isNoAlias(const Value *V1, uint64_t V1Size, const Value *V2,
|
||||
uint64_t V2Size) {
|
||||
return isNoAlias(MemoryLocation(V1, V1Size), MemoryLocation(V2, V2Size));
|
||||
}
|
||||
|
||||
/// isNoAlias - A convenience wrapper.
|
||||
|
||||
/// A convenience wrapper around the \c isNoAlias helper interface.
|
||||
bool isNoAlias(const Value *V1, const Value *V2) {
|
||||
return isNoAlias(Location(V1), Location(V2));
|
||||
return isNoAlias(MemoryLocation(V1), MemoryLocation(V2));
|
||||
}
|
||||
|
||||
/// isMustAlias - A convenience wrapper.
|
||||
bool isMustAlias(const Location &LocA, const Location &LocB) {
|
||||
|
||||
/// A trivial helper function to check to see if the specified pointers are
|
||||
/// must-alias.
|
||||
bool isMustAlias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
|
||||
return alias(LocA, LocB) == MustAlias;
|
||||
}
|
||||
|
||||
/// isMustAlias - A convenience wrapper.
|
||||
/// A convenience wrapper around the \c isMustAlias helper interface.
|
||||
bool isMustAlias(const Value *V1, const Value *V2) {
|
||||
return alias(V1, 1, V2, 1) == MustAlias;
|
||||
}
|
||||
|
||||
/// pointsToConstantMemory - If the specified memory location is
|
||||
/// known to be constant, return true. If OrLocal is true and the
|
||||
/// specified memory location is known to be "local" (derived from
|
||||
/// an alloca), return true. Otherwise return false.
|
||||
virtual bool pointsToConstantMemory(const Location &Loc,
|
||||
|
||||
/// Checks whether the given location points to constant memory, or if
|
||||
/// \p OrLocal is true whether it points to a local alloca.
|
||||
virtual bool pointsToConstantMemory(const MemoryLocation &Loc,
|
||||
bool OrLocal = false);
|
||||
|
||||
/// pointsToConstantMemory - A convenient wrapper.
|
||||
/// A convenience wrapper around the primary \c pointsToConstantMemory
|
||||
/// interface.
|
||||
bool pointsToConstantMemory(const Value *P, bool OrLocal = false) {
|
||||
return pointsToConstantMemory(Location(P), OrLocal);
|
||||
return pointsToConstantMemory(MemoryLocation(P), OrLocal);
|
||||
}
|
||||
|
||||
/// @}
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Simple mod/ref information...
|
||||
/// \name Simple mod/ref information
|
||||
/// @{
|
||||
|
||||
/// Get the ModRef info associated with a pointer argument of a callsite. The
|
||||
/// result's bits are set to indicate the allowed aliasing ModRef kinds. Note
|
||||
/// that these bits do not necessarily account for the overall behavior of
|
||||
/// the function, but rather only provide additional per-argument
|
||||
/// information.
|
||||
virtual ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
|
||||
|
||||
/// Return the behavior of the given call site.
|
||||
virtual FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
|
||||
/// Return the behavior when calling the given function.
|
||||
virtual FunctionModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
/// Checks if the specified call is known to never read or write memory.
|
||||
///
|
||||
|
||||
/// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are
|
||||
/// bits which may be or'd together.
|
||||
///
|
||||
enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 };
|
||||
|
||||
/// These values define additional bits used to define the
|
||||
/// ModRefBehavior values.
|
||||
enum { Nowhere = 0, ArgumentPointees = 4, Anywhere = 8 | ArgumentPointees };
|
||||
|
||||
/// ModRefBehavior - Summary of how a function affects memory in the program.
|
||||
/// Loads from constant globals are not considered memory accesses for this
|
||||
/// interface. Also, functions may freely modify stack space local to their
|
||||
/// invocation without having to report it through these interfaces.
|
||||
enum ModRefBehavior {
|
||||
/// DoesNotAccessMemory - This function does not perform any non-local loads
|
||||
/// or stores to memory.
|
||||
///
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readnone' attribute.
|
||||
/// This property corresponds to the IntrNoMem LLVM intrinsic flag.
|
||||
DoesNotAccessMemory = Nowhere | NoModRef,
|
||||
|
||||
/// OnlyReadsArgumentPointees - The only memory references in this function
|
||||
/// (if it has any) are non-volatile loads from objects pointed to by its
|
||||
/// pointer-typed arguments, with arbitrary offsets.
|
||||
///
|
||||
/// This property corresponds to the IntrReadArgMem LLVM intrinsic flag.
|
||||
OnlyReadsArgumentPointees = ArgumentPointees | Ref,
|
||||
|
||||
/// OnlyAccessesArgumentPointees - The only memory references in this
|
||||
/// function (if it has any) are non-volatile loads and stores from objects
|
||||
/// pointed to by its pointer-typed arguments, with arbitrary offsets.
|
||||
///
|
||||
/// This property corresponds to the IntrReadWriteArgMem LLVM intrinsic flag.
|
||||
OnlyAccessesArgumentPointees = ArgumentPointees | ModRef,
|
||||
|
||||
/// OnlyReadsMemory - This function does not perform any non-local stores or
|
||||
/// volatile loads, but may read from any memory location.
|
||||
///
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
/// This property corresponds to the LLVM IR 'readonly' attribute.
|
||||
/// This property corresponds to the IntrReadMem LLVM intrinsic flag.
|
||||
OnlyReadsMemory = Anywhere | Ref,
|
||||
|
||||
/// UnknownModRefBehavior - This indicates that the function could not be
|
||||
/// classified into one of the behaviors above.
|
||||
UnknownModRefBehavior = Anywhere | ModRef
|
||||
};
|
||||
|
||||
/// Get the location associated with a pointer argument of a callsite.
|
||||
/// The mask bits are set to indicate the allowed aliasing ModRef kinds.
|
||||
/// Note that these mask bits do not necessarily account for the overall
|
||||
/// behavior of the function, but rather only provide additional
|
||||
/// per-argument information.
|
||||
virtual Location getArgLocation(ImmutableCallSite CS, unsigned ArgIdx,
|
||||
ModRefResult &Mask);
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given call site.
|
||||
virtual ModRefBehavior getModRefBehavior(ImmutableCallSite CS);
|
||||
|
||||
/// getModRefBehavior - Return the behavior when calling the given function.
|
||||
/// For use when the call site is not known.
|
||||
virtual ModRefBehavior getModRefBehavior(const Function *F);
|
||||
|
||||
/// doesNotAccessMemory - If the specified call is known to never read or
|
||||
/// write memory, return true. If the call only reads from known-constant
|
||||
/// memory, it is also legal to return true. Calls that unwind the stack
|
||||
/// are legal for this predicate.
|
||||
/// Note that if the call only reads from known-constant memory, it is also
|
||||
/// legal to return true. Also, calls that unwind the stack are legal for
|
||||
/// this predicate.
|
||||
///
|
||||
/// Many optimizations (such as CSE and LICM) can be performed on such calls
|
||||
/// without worrying about aliasing properties, and many calls have this
|
||||
/// property (e.g. calls to 'sin' and 'cos').
|
||||
///
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
///
|
||||
bool doesNotAccessMemory(ImmutableCallSite CS) {
|
||||
return getModRefBehavior(CS) == DoesNotAccessMemory;
|
||||
return getModRefBehavior(CS) == FMRB_DoesNotAccessMemory;
|
||||
}
|
||||
|
||||
/// doesNotAccessMemory - If the specified function is known to never read or
|
||||
/// write memory, return true. For use when the call site is not known.
|
||||
/// Checks if the specified function is known to never read or write memory.
|
||||
///
|
||||
/// Note that if the function only reads from known-constant memory, it is
|
||||
/// also legal to return true. Also, function that unwind the stack are legal
|
||||
/// for this predicate.
|
||||
///
|
||||
/// Many optimizations (such as CSE and LICM) can be performed on such calls
|
||||
/// to such functions without worrying about aliasing properties, and many
|
||||
/// functions have this property (e.g. 'sin' and 'cos').
|
||||
///
|
||||
/// This property corresponds to the GCC 'const' attribute.
|
||||
bool doesNotAccessMemory(const Function *F) {
|
||||
return getModRefBehavior(F) == DoesNotAccessMemory;
|
||||
return getModRefBehavior(F) == FMRB_DoesNotAccessMemory;
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - If the specified call is known to only read from
|
||||
/// non-volatile memory (or not access memory at all), return true. Calls
|
||||
/// that unwind the stack are legal for this predicate.
|
||||
/// Checks if the specified call is known to only read from non-volatile
|
||||
/// memory (or not access memory at all).
|
||||
///
|
||||
/// Calls that unwind the stack are legal for this predicate.
|
||||
///
|
||||
/// This property allows many common optimizations to be performed in the
|
||||
/// absence of interfering store instructions, such as CSE of strlen calls.
|
||||
///
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
///
|
||||
bool onlyReadsMemory(ImmutableCallSite CS) {
|
||||
return onlyReadsMemory(getModRefBehavior(CS));
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - If the specified function is known to only read from
|
||||
/// non-volatile memory (or not access memory at all), return true. For use
|
||||
/// when the call site is not known.
|
||||
/// Checks if the specified function is known to only read from non-volatile
|
||||
/// memory (or not access memory at all).
|
||||
///
|
||||
/// Functions that unwind the stack are legal for this predicate.
|
||||
///
|
||||
/// This property allows many common optimizations to be performed in the
|
||||
/// absence of interfering store instructions, such as CSE of strlen calls.
|
||||
///
|
||||
/// This property corresponds to the GCC 'pure' attribute.
|
||||
bool onlyReadsMemory(const Function *F) {
|
||||
return onlyReadsMemory(getModRefBehavior(F));
|
||||
}
|
||||
|
||||
/// onlyReadsMemory - Return true if functions with the specified behavior are
|
||||
/// known to only read from non-volatile memory (or not access memory at all).
|
||||
///
|
||||
static bool onlyReadsMemory(ModRefBehavior MRB) {
|
||||
return !(MRB & Mod);
|
||||
/// Checks if functions with the specified behavior are known to only read
|
||||
/// from non-volatile memory (or not access memory at all).
|
||||
static bool onlyReadsMemory(FunctionModRefBehavior MRB) {
|
||||
return !(MRB & MRI_Mod);
|
||||
}
|
||||
|
||||
/// onlyAccessesArgPointees - Return true if functions with the specified
|
||||
/// behavior are known to read and write at most from objects pointed to by
|
||||
/// their pointer-typed arguments (with arbitrary offsets).
|
||||
///
|
||||
static bool onlyAccessesArgPointees(ModRefBehavior MRB) {
|
||||
return !(MRB & Anywhere & ~ArgumentPointees);
|
||||
/// Checks if functions with the specified behavior are known to read and
|
||||
/// write at most from objects pointed to by their pointer-typed arguments
|
||||
/// (with arbitrary offsets).
|
||||
static bool onlyAccessesArgPointees(FunctionModRefBehavior MRB) {
|
||||
return !(MRB & FMRL_Anywhere & ~FMRL_ArgumentPointees);
|
||||
}
|
||||
|
||||
/// doesAccessArgPointees - Return true if functions with the specified
|
||||
/// behavior are known to potentially read or write from objects pointed
|
||||
/// to be their pointer-typed arguments (with arbitrary offsets).
|
||||
///
|
||||
static bool doesAccessArgPointees(ModRefBehavior MRB) {
|
||||
return (MRB & ModRef) && (MRB & ArgumentPointees);
|
||||
/// Checks if functions with the specified behavior are known to potentially
|
||||
/// read or write from objects pointed to be their pointer-typed arguments
|
||||
/// (with arbitrary offsets).
|
||||
static bool doesAccessArgPointees(FunctionModRefBehavior MRB) {
|
||||
return (MRB & MRI_ModRef) && (MRB & FMRL_ArgumentPointees);
|
||||
}
|
||||
|
||||
/// getModRefInfo - Return information about whether or not an
|
||||
/// instruction may read or write memory (without regard to a
|
||||
/// specific location)
|
||||
ModRefResult getModRefInfo(const Instruction *I) {
|
||||
/// getModRefInfo (for call sites) - Return information about whether
|
||||
/// a particular call site modifies or reads the specified memory location.
|
||||
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc);
|
||||
|
||||
/// getModRefInfo (for call sites) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS, const Value *P,
|
||||
uint64_t Size) {
|
||||
return getModRefInfo(CS, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for calls) - Return information about whether
|
||||
/// a particular call modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(const CallInst *C, const MemoryLocation &Loc) {
|
||||
return getModRefInfo(ImmutableCallSite(C), Loc);
|
||||
}
|
||||
|
||||
/// getModRefInfo (for calls) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(C, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for invokes) - Return information about whether
|
||||
/// a particular invoke modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(const InvokeInst *I, const MemoryLocation &Loc) {
|
||||
return getModRefInfo(ImmutableCallSite(I), Loc);
|
||||
}
|
||||
|
||||
/// getModRefInfo (for invokes) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(const InvokeInst *I, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(I, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for loads) - Return information about whether
|
||||
/// a particular load modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(const LoadInst *L, const MemoryLocation &Loc);
|
||||
|
||||
/// getModRefInfo (for loads) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(L, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for stores) - Return information about whether
|
||||
/// a particular store modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(const StoreInst *S, const MemoryLocation &Loc);
|
||||
|
||||
/// getModRefInfo (for stores) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(S, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for fences) - Return information about whether
|
||||
/// a particular store modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(const FenceInst *S, const MemoryLocation &Loc) {
|
||||
// Conservatively correct. (We could possibly be a bit smarter if
|
||||
// Loc is a alloca that doesn't escape.)
|
||||
return MRI_ModRef;
|
||||
}
|
||||
|
||||
/// getModRefInfo (for fences) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(S, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for cmpxchges) - Return information about whether
|
||||
/// a particular cmpxchg modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX,
|
||||
const MemoryLocation &Loc);
|
||||
|
||||
/// getModRefInfo (for cmpxchges) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(const AtomicCmpXchgInst *CX, const Value *P,
|
||||
unsigned Size) {
|
||||
return getModRefInfo(CX, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for atomicrmws) - Return information about whether
|
||||
/// a particular atomicrmw modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const MemoryLocation &Loc);
|
||||
|
||||
/// getModRefInfo (for atomicrmws) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(const AtomicRMWInst *RMW, const Value *P,
|
||||
unsigned Size) {
|
||||
return getModRefInfo(RMW, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for va_args) - Return information about whether
|
||||
/// a particular va_arg modifies or reads the specified memory location.
|
||||
ModRefInfo getModRefInfo(const VAArgInst *I, const MemoryLocation &Loc);
|
||||
|
||||
/// getModRefInfo (for va_args) - A convenience wrapper.
|
||||
ModRefInfo getModRefInfo(const VAArgInst *I, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(I, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// Check whether or not an instruction may read or write memory (without
|
||||
/// regard to a specific location).
|
||||
///
|
||||
/// For function calls, this delegates to the alias-analysis specific
|
||||
/// call-site mod-ref behavior queries. Otherwise it delegates to the generic
|
||||
/// mod ref information query without a location.
|
||||
ModRefInfo getModRefInfo(const Instruction *I) {
|
||||
if (auto CS = ImmutableCallSite(I)) {
|
||||
auto MRB = getModRefBehavior(CS);
|
||||
if (MRB & ModRef)
|
||||
return ModRef;
|
||||
else if (MRB & Ref)
|
||||
return Ref;
|
||||
else if (MRB & Mod)
|
||||
return Mod;
|
||||
return NoModRef;
|
||||
if (MRB & MRI_ModRef)
|
||||
return MRI_ModRef;
|
||||
else if (MRB & MRI_Ref)
|
||||
return MRI_Ref;
|
||||
else if (MRB & MRI_Mod)
|
||||
return MRI_Mod;
|
||||
return MRI_NoModRef;
|
||||
}
|
||||
|
||||
return getModRefInfo(I, Location());
|
||||
return getModRefInfo(I, MemoryLocation());
|
||||
}
|
||||
|
||||
/// getModRefInfo - Return information about whether or not an instruction may
|
||||
/// read or write the specified memory location. An instruction
|
||||
/// that doesn't read or write memory may be trivially LICM'd for example.
|
||||
ModRefResult getModRefInfo(const Instruction *I,
|
||||
const Location &Loc) {
|
||||
/// Check whether or not an instruction may read or write the specified
|
||||
/// memory location.
|
||||
///
|
||||
/// An instruction that doesn't read or write memory may be trivially LICM'd
|
||||
/// for example.
|
||||
///
|
||||
/// This primarily delegates to specific helpers above.
|
||||
ModRefInfo getModRefInfo(const Instruction *I, const MemoryLocation &Loc) {
|
||||
switch (I->getOpcode()) {
|
||||
case Instruction::VAArg: return getModRefInfo((const VAArgInst*)I, Loc);
|
||||
case Instruction::Load: return getModRefInfo((const LoadInst*)I, Loc);
|
||||
@ -343,201 +481,71 @@ public:
|
||||
return getModRefInfo((const AtomicRMWInst*)I, Loc);
|
||||
case Instruction::Call: return getModRefInfo((const CallInst*)I, Loc);
|
||||
case Instruction::Invoke: return getModRefInfo((const InvokeInst*)I,Loc);
|
||||
default: return NoModRef;
|
||||
default:
|
||||
return MRI_NoModRef;
|
||||
}
|
||||
}
|
||||
|
||||
/// getModRefInfo - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const Instruction *I,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
/// A convenience wrapper for constructing the memory location.
|
||||
ModRefInfo getModRefInfo(const Instruction *I, const Value *P,
|
||||
uint64_t Size) {
|
||||
return getModRefInfo(I, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for call sites) - Return information about whether
|
||||
/// a particular call site modifies or reads the specified memory location.
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Location &Loc);
|
||||
/// Return information about whether a call and an instruction may refer to
|
||||
/// the same memory locations.
|
||||
ModRefInfo getModRefInfo(Instruction *I, ImmutableCallSite Call);
|
||||
|
||||
/// getModRefInfo (for call sites) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(CS, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for calls) - Return information about whether
|
||||
/// a particular call modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const CallInst *C, const Location &Loc) {
|
||||
return getModRefInfo(ImmutableCallSite(C), Loc);
|
||||
}
|
||||
|
||||
/// getModRefInfo (for calls) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const CallInst *C, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(C, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for invokes) - Return information about whether
|
||||
/// a particular invoke modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const InvokeInst *I,
|
||||
const Location &Loc) {
|
||||
return getModRefInfo(ImmutableCallSite(I), Loc);
|
||||
}
|
||||
|
||||
/// getModRefInfo (for invokes) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const InvokeInst *I,
|
||||
const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for loads) - Return information about whether
|
||||
/// a particular load modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const LoadInst *L, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for loads) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const LoadInst *L, const Value *P, uint64_t Size) {
|
||||
return getModRefInfo(L, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for stores) - Return information about whether
|
||||
/// a particular store modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const StoreInst *S, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for stores) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const StoreInst *S, const Value *P, uint64_t Size){
|
||||
return getModRefInfo(S, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for fences) - Return information about whether
|
||||
/// a particular store modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const FenceInst *S, const Location &Loc) {
|
||||
// Conservatively correct. (We could possibly be a bit smarter if
|
||||
// Loc is a alloca that doesn't escape.)
|
||||
return ModRef;
|
||||
}
|
||||
|
||||
/// getModRefInfo (for fences) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const FenceInst *S, const Value *P, uint64_t Size){
|
||||
return getModRefInfo(S, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for cmpxchges) - Return information about whether
|
||||
/// a particular cmpxchg modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for cmpxchges) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const AtomicCmpXchgInst *CX,
|
||||
const Value *P, unsigned Size) {
|
||||
return getModRefInfo(CX, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for atomicrmws) - Return information about whether
|
||||
/// a particular atomicrmw modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const AtomicRMWInst *RMW, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for atomicrmws) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const AtomicRMWInst *RMW,
|
||||
const Value *P, unsigned Size) {
|
||||
return getModRefInfo(RMW, Location(P, Size));
|
||||
}
|
||||
|
||||
/// getModRefInfo (for va_args) - Return information about whether
|
||||
/// a particular va_arg modifies or reads the specified memory location.
|
||||
ModRefResult getModRefInfo(const VAArgInst* I, const Location &Loc);
|
||||
|
||||
/// getModRefInfo (for va_args) - A convenience wrapper.
|
||||
ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){
|
||||
return getModRefInfo(I, Location(P, Size));
|
||||
}
|
||||
/// getModRefInfo - Return information about whether a call and an instruction
|
||||
/// may refer to the same memory locations.
|
||||
ModRefResult getModRefInfo(Instruction *I,
|
||||
ImmutableCallSite Call);
|
||||
|
||||
/// getModRefInfo - Return information about whether two call sites may refer
|
||||
/// to the same set of memory locations. See
|
||||
/// Return information about whether two call sites may refer to the same set
|
||||
/// of memory locations. See the AA documentation for details:
|
||||
/// http://llvm.org/docs/AliasAnalysis.html#ModRefInfo
|
||||
/// for details.
|
||||
virtual ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2);
|
||||
virtual ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2);
|
||||
|
||||
/// callCapturesBefore - Return information about whether a particular call
|
||||
/// site modifies or reads the specified memory location.
|
||||
ModRefResult callCapturesBefore(const Instruction *I,
|
||||
const AliasAnalysis::Location &MemLoc,
|
||||
DominatorTree *DT);
|
||||
/// \brief Return information about whether a particular call site modifies
|
||||
/// or reads the specified memory location \p MemLoc before instruction \p I
|
||||
/// in a BasicBlock. A ordered basic block \p OBB can be used to speed up
|
||||
/// instruction ordering queries inside the BasicBlock containing \p I.
|
||||
ModRefInfo callCapturesBefore(const Instruction *I,
|
||||
const MemoryLocation &MemLoc, DominatorTree *DT,
|
||||
OrderedBasicBlock *OBB = nullptr);
|
||||
|
||||
/// callCapturesBefore - A convenience wrapper.
|
||||
ModRefResult callCapturesBefore(const Instruction *I, const Value *P,
|
||||
uint64_t Size, DominatorTree *DT) {
|
||||
return callCapturesBefore(I, Location(P, Size), DT);
|
||||
/// \brief A convenience wrapper to synthesize a memory location.
|
||||
ModRefInfo callCapturesBefore(const Instruction *I, const Value *P,
|
||||
uint64_t Size, DominatorTree *DT,
|
||||
OrderedBasicBlock *OBB = nullptr) {
|
||||
return callCapturesBefore(I, MemoryLocation(P, Size), DT, OBB);
|
||||
}
|
||||
|
||||
/// @}
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Higher level methods for querying mod/ref information.
|
||||
///
|
||||
/// \name Higher level methods for querying mod/ref information.
|
||||
/// @{
|
||||
|
||||
/// canBasicBlockModify - Return true if it is possible for execution of the
|
||||
/// specified basic block to modify the location Loc.
|
||||
bool canBasicBlockModify(const BasicBlock &BB, const Location &Loc);
|
||||
/// Check if it is possible for execution of the specified basic block to
|
||||
/// modify the location Loc.
|
||||
bool canBasicBlockModify(const BasicBlock &BB, const MemoryLocation &Loc);
|
||||
|
||||
/// canBasicBlockModify - A convenience wrapper.
|
||||
bool canBasicBlockModify(const BasicBlock &BB, const Value *P, uint64_t Size){
|
||||
return canBasicBlockModify(BB, Location(P, Size));
|
||||
/// A convenience wrapper synthesizing a memory location.
|
||||
bool canBasicBlockModify(const BasicBlock &BB, const Value *P,
|
||||
uint64_t Size) {
|
||||
return canBasicBlockModify(BB, MemoryLocation(P, Size));
|
||||
}
|
||||
|
||||
/// canInstructionRangeModRef - Return true if it is possible for the
|
||||
/// execution of the specified instructions to mod\ref (according to the
|
||||
/// mode) the location Loc. The instructions to consider are all
|
||||
/// of the instructions in the range of [I1,I2] INCLUSIVE.
|
||||
/// I1 and I2 must be in the same basic block.
|
||||
bool canInstructionRangeModRef(const Instruction &I1,
|
||||
const Instruction &I2, const Location &Loc,
|
||||
const ModRefResult Mode);
|
||||
|
||||
/// canInstructionRangeModRef - A convenience wrapper.
|
||||
bool canInstructionRangeModRef(const Instruction &I1,
|
||||
const Instruction &I2, const Value *Ptr,
|
||||
uint64_t Size, const ModRefResult Mode) {
|
||||
return canInstructionRangeModRef(I1, I2, Location(Ptr, Size), Mode);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
/// Methods that clients should call when they transform the program to allow
|
||||
/// alias analyses to update their internal data structures. Note that these
|
||||
/// methods may be called on any instruction, regardless of whether or not
|
||||
/// they have pointer-analysis implications.
|
||||
/// Check if it is possible for the execution of the specified instructions
|
||||
/// to mod\ref (according to the mode) the location Loc.
|
||||
///
|
||||
/// The instructions to consider are all of the instructions in the range of
|
||||
/// [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block.
|
||||
bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2,
|
||||
const MemoryLocation &Loc,
|
||||
const ModRefInfo Mode);
|
||||
|
||||
/// deleteValue - This method should be called whenever an LLVM Value is
|
||||
/// deleted from the program, for example when an instruction is found to be
|
||||
/// redundant and is eliminated.
|
||||
///
|
||||
virtual void deleteValue(Value *V);
|
||||
|
||||
/// copyValue - This method should be used whenever a preexisting value in the
|
||||
/// program is copied or cloned, introducing a new value. Note that analysis
|
||||
/// implementations should tolerate clients that use this method to introduce
|
||||
/// the same value multiple times: if the analysis already knows about a
|
||||
/// value, it should ignore the request.
|
||||
///
|
||||
virtual void copyValue(Value *From, Value *To);
|
||||
|
||||
/// addEscapingUse - This method should be used whenever an escaping use is
|
||||
/// added to a pointer value. Analysis implementations may either return
|
||||
/// conservative responses for that value in the future, or may recompute
|
||||
/// some or all internal state to continue providing precise responses.
|
||||
///
|
||||
/// Escaping uses are considered by anything _except_ the following:
|
||||
/// - GEPs or bitcasts of the pointer
|
||||
/// - Loads through the pointer
|
||||
/// - Stores through (but not of) the pointer
|
||||
virtual void addEscapingUse(Use &U);
|
||||
|
||||
/// replaceWithNewValue - This method is the obvious combination of the two
|
||||
/// above, and it provided as a helper to simplify client code.
|
||||
///
|
||||
void replaceWithNewValue(Value *Old, Value *New) {
|
||||
copyValue(Old, New);
|
||||
deleteValue(Old);
|
||||
/// A convenience wrapper synthesizing a memory location.
|
||||
bool canInstructionRangeModRef(const Instruction &I1, const Instruction &I2,
|
||||
const Value *Ptr, uint64_t Size,
|
||||
const ModRefInfo Mode) {
|
||||
return canInstructionRangeModRef(I1, I2, MemoryLocation(Ptr, Size), Mode);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -117,24 +117,30 @@ class AliasSet : public ilist_node<AliasSet> {
|
||||
// AliasSets forwarding to it.
|
||||
unsigned RefCount : 28;
|
||||
|
||||
/// AccessType - Keep track of whether this alias set merely refers to the
|
||||
/// locations of memory, whether it modifies the memory, or whether it does
|
||||
/// both. The lattice goes from "NoModRef" to either Refs or Mods, then to
|
||||
/// ModRef as necessary.
|
||||
/// The kinds of access this alias set models.
|
||||
///
|
||||
enum AccessType {
|
||||
NoModRef = 0, Refs = 1, // Ref = bit 1
|
||||
Mods = 2, ModRef = 3 // Mod = bit 2
|
||||
/// We keep track of whether this alias set merely refers to the locations of
|
||||
/// memory (and not any particular access), whether it modifies or references
|
||||
/// the memory, or whether it does both. The lattice goes from "NoAccess" to
|
||||
/// either RefAccess or ModAccess, then to ModRefAccess as necessary.
|
||||
enum AccessLattice {
|
||||
NoAccess = 0,
|
||||
RefAccess = 1,
|
||||
ModAccess = 2,
|
||||
ModRefAccess = RefAccess | ModAccess
|
||||
};
|
||||
unsigned AccessTy : 2;
|
||||
unsigned Access : 2;
|
||||
|
||||
/// AliasType - Keep track the relationships between the pointers in the set.
|
||||
/// Lattice goes from MustAlias to MayAlias.
|
||||
/// The kind of alias relationship between pointers of the set.
|
||||
///
|
||||
enum AliasType {
|
||||
MustAlias = 0, MayAlias = 1
|
||||
/// These represent conservatively correct alias results between any members
|
||||
/// of the set. We represent these independently of the values of alias
|
||||
/// results in order to pack it into a single bit. Lattice goes from
|
||||
/// MustAlias to MayAlias.
|
||||
enum AliasLattice {
|
||||
SetMustAlias = 0, SetMayAlias = 1
|
||||
};
|
||||
unsigned AliasTy : 1;
|
||||
unsigned Alias : 1;
|
||||
|
||||
// Volatile - True if this alias set contains volatile loads or stores.
|
||||
bool Volatile : 1;
|
||||
@ -153,10 +159,10 @@ class AliasSet : public ilist_node<AliasSet> {
|
||||
|
||||
public:
|
||||
/// Accessors...
|
||||
bool isRef() const { return AccessTy & Refs; }
|
||||
bool isMod() const { return AccessTy & Mods; }
|
||||
bool isMustAlias() const { return AliasTy == MustAlias; }
|
||||
bool isMayAlias() const { return AliasTy == MayAlias; }
|
||||
bool isRef() const { return Access & RefAccess; }
|
||||
bool isMod() const { return Access & ModAccess; }
|
||||
bool isMustAlias() const { return Alias == SetMustAlias; }
|
||||
bool isMayAlias() const { return Alias == SetMayAlias; }
|
||||
|
||||
// isVolatile - Return true if this alias set contains volatile loads or
|
||||
// stores.
|
||||
@ -218,7 +224,7 @@ private:
|
||||
friend struct ilist_sentinel_traits<AliasSet>;
|
||||
AliasSet()
|
||||
: PtrList(nullptr), PtrListEnd(&PtrList), Forward(nullptr), RefCount(0),
|
||||
AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) {
|
||||
Access(NoAccess), Alias(SetMustAlias), Volatile(false) {
|
||||
}
|
||||
|
||||
AliasSet(const AliasSet &AS) = delete;
|
||||
@ -419,11 +425,11 @@ private:
|
||||
}
|
||||
|
||||
AliasSet &addPointer(Value *P, uint64_t Size, const AAMDNodes &AAInfo,
|
||||
AliasSet::AccessType E,
|
||||
AliasSet::AccessLattice E,
|
||||
bool &NewSet) {
|
||||
NewSet = false;
|
||||
AliasSet &AS = getAliasSetForPointer(P, Size, AAInfo, &NewSet);
|
||||
AS.AccessTy |= E;
|
||||
AS.Access |= E;
|
||||
return AS;
|
||||
}
|
||||
AliasSet *findAliasSetForPointer(const Value *Ptr, uint64_t Size,
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
|
||||
/// \brief Add an @llvm.assume intrinsic to this function's cache.
|
||||
///
|
||||
/// The call passed in must be an instruction within this fuction and must
|
||||
/// The call passed in must be an instruction within this function and must
|
||||
/// not already be in the cache.
|
||||
void registerAssumption(CallInst *CI);
|
||||
|
||||
@ -79,7 +79,7 @@ public:
|
||||
}
|
||||
|
||||
/// \brief Access the list of assumption handles currently tracked for this
|
||||
/// fuction.
|
||||
/// function.
|
||||
///
|
||||
/// Note that these produce weak handles that may be null. The caller must
|
||||
/// handle that case.
|
||||
|
@ -21,26 +21,20 @@
|
||||
namespace llvm {
|
||||
|
||||
class BranchProbabilityInfo;
|
||||
class LoopInfo;
|
||||
template <class BlockT> class BlockFrequencyInfoImpl;
|
||||
|
||||
/// BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to
|
||||
/// estimate IR basic block frequencies.
|
||||
class BlockFrequencyInfo : public FunctionPass {
|
||||
class BlockFrequencyInfo {
|
||||
typedef BlockFrequencyInfoImpl<BasicBlock> ImplType;
|
||||
std::unique_ptr<ImplType> BFI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BlockFrequencyInfo();
|
||||
BlockFrequencyInfo(const Function &F, const BranchProbabilityInfo &BPI,
|
||||
const LoopInfo &LI);
|
||||
|
||||
~BlockFrequencyInfo() override;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
|
||||
bool runOnFunction(Function &F) override;
|
||||
void releaseMemory() override;
|
||||
void print(raw_ostream &O, const Module *M) const override;
|
||||
const Function *getFunction() const;
|
||||
void view() const;
|
||||
|
||||
@ -51,6 +45,10 @@ public:
|
||||
/// floating points.
|
||||
BlockFrequency getBlockFreq(const BasicBlock *BB) const;
|
||||
|
||||
/// calculate - compute block frequency info for the given function.
|
||||
void calculate(const Function &F, const BranchProbabilityInfo &BPI,
|
||||
const LoopInfo &LI);
|
||||
|
||||
// Print the block frequency Freq to OS using the current functions entry
|
||||
// frequency to convert freq into a relative decimal form.
|
||||
raw_ostream &printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const;
|
||||
@ -60,7 +58,28 @@ public:
|
||||
raw_ostream &printBlockFreq(raw_ostream &OS, const BasicBlock *BB) const;
|
||||
|
||||
uint64_t getEntryFreq() const;
|
||||
void releaseMemory();
|
||||
void print(raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
/// \brief Legacy analysis pass which computes \c BlockFrequencyInfo.
|
||||
class BlockFrequencyInfoWrapperPass : public FunctionPass {
|
||||
BlockFrequencyInfo BFI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BlockFrequencyInfoWrapperPass();
|
||||
~BlockFrequencyInfoWrapperPass() override;
|
||||
|
||||
BlockFrequencyInfo &getBFI() { return BFI; }
|
||||
const BlockFrequencyInfo &getBFI() const { return BFI; }
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
|
||||
bool runOnFunction(Function &F) override;
|
||||
void releaseMemory() override;
|
||||
void print(raw_ostream &OS, const Module *M) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -196,23 +196,26 @@ public:
|
||||
struct LoopData {
|
||||
typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap;
|
||||
typedef SmallVector<BlockNode, 4> NodeList;
|
||||
LoopData *Parent; ///< The parent loop.
|
||||
bool IsPackaged; ///< Whether this has been packaged.
|
||||
uint32_t NumHeaders; ///< Number of headers.
|
||||
ExitMap Exits; ///< Successor edges (and weights).
|
||||
NodeList Nodes; ///< Header and the members of the loop.
|
||||
BlockMass BackedgeMass; ///< Mass returned to loop header.
|
||||
typedef SmallVector<BlockMass, 1> HeaderMassList;
|
||||
LoopData *Parent; ///< The parent loop.
|
||||
bool IsPackaged; ///< Whether this has been packaged.
|
||||
uint32_t NumHeaders; ///< Number of headers.
|
||||
ExitMap Exits; ///< Successor edges (and weights).
|
||||
NodeList Nodes; ///< Header and the members of the loop.
|
||||
HeaderMassList BackedgeMass; ///< Mass returned to each loop header.
|
||||
BlockMass Mass;
|
||||
Scaled64 Scale;
|
||||
|
||||
LoopData(LoopData *Parent, const BlockNode &Header)
|
||||
: Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header) {}
|
||||
: Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header),
|
||||
BackedgeMass(1) {}
|
||||
template <class It1, class It2>
|
||||
LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther,
|
||||
It2 LastOther)
|
||||
: Parent(Parent), IsPackaged(false), Nodes(FirstHeader, LastHeader) {
|
||||
NumHeaders = Nodes.size();
|
||||
Nodes.insert(Nodes.end(), FirstOther, LastOther);
|
||||
BackedgeMass.resize(NumHeaders);
|
||||
}
|
||||
bool isHeader(const BlockNode &Node) const {
|
||||
if (isIrreducible())
|
||||
@ -223,6 +226,14 @@ public:
|
||||
BlockNode getHeader() const { return Nodes[0]; }
|
||||
bool isIrreducible() const { return NumHeaders > 1; }
|
||||
|
||||
HeaderMassList::difference_type getHeaderIndex(const BlockNode &B) {
|
||||
assert(isHeader(B) && "this is only valid on loop header blocks");
|
||||
if (isIrreducible())
|
||||
return std::lower_bound(Nodes.begin(), Nodes.begin() + NumHeaders, B) -
|
||||
Nodes.begin();
|
||||
return 0;
|
||||
}
|
||||
|
||||
NodeList::const_iterator members_begin() const {
|
||||
return Nodes.begin() + NumHeaders;
|
||||
}
|
||||
@ -431,6 +442,16 @@ public:
|
||||
/// \brief Compute the loop scale for a loop.
|
||||
void computeLoopScale(LoopData &Loop);
|
||||
|
||||
/// Adjust the mass of all headers in an irreducible loop.
|
||||
///
|
||||
/// Initially, irreducible loops are assumed to distribute their mass
|
||||
/// equally among its headers. This can lead to wrong frequency estimates
|
||||
/// since some headers may be executed more frequently than others.
|
||||
///
|
||||
/// This adjusts header mass distribution so it matches the weights of
|
||||
/// the backedges going into each of the loop headers.
|
||||
void adjustLoopHeaderMass(LoopData &Loop);
|
||||
|
||||
/// \brief Package up a loop.
|
||||
void packageLoop(LoopData &Loop);
|
||||
|
||||
@ -695,6 +716,17 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
|
||||
/// - Distribute the mass accordingly, dithering to minimize mass loss,
|
||||
/// as described in \a distributeMass().
|
||||
///
|
||||
/// In the case of irreducible loops, instead of a single loop header,
|
||||
/// there will be several. The computation of backedge masses is similar
|
||||
/// but instead of having a single backedge mass, there will be one
|
||||
/// backedge per loop header. In these cases, each backedge will carry
|
||||
/// a mass proportional to the edge weights along the corresponding
|
||||
/// path.
|
||||
///
|
||||
/// At the end of propagation, the full mass assigned to the loop will be
|
||||
/// distributed among the loop headers proportionally according to the
|
||||
/// mass flowing through their backedges.
|
||||
///
|
||||
/// Finally, calculate the loop scale from the accumulated backedge mass.
|
||||
///
|
||||
/// 3. Distribute mass in the function (\a computeMassInFunction()).
|
||||
@ -735,11 +767,6 @@ void IrreducibleGraph::addEdges(const BlockNode &Node,
|
||||
/// as sub-loops, rather than arbitrarily shoving the problematic
|
||||
/// blocks into the headers of the main irreducible SCC.
|
||||
///
|
||||
/// - Backedge frequencies are assumed to be evenly split between the
|
||||
/// headers of a given irreducible SCC. Instead, we could track the
|
||||
/// backedge mass separately for each header, and adjust their relative
|
||||
/// frequencies.
|
||||
///
|
||||
/// - Entry frequencies are assumed to be evenly split between the
|
||||
/// headers of a given irreducible SCC, which is the only option if we
|
||||
/// need to compute mass in the SCC before its parent loop. Instead,
|
||||
@ -846,7 +873,7 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
|
||||
///
|
||||
/// \pre \a computeMassInLoop() has been called for each subloop of \c
|
||||
/// OuterLoop.
|
||||
/// \pre \c Insert points at the the last loop successfully processed by \a
|
||||
/// \pre \c Insert points at the last loop successfully processed by \a
|
||||
/// computeMassInLoop().
|
||||
/// \pre \c OuterLoop has irreducible SCCs.
|
||||
void computeIrreducibleMass(LoopData *OuterLoop,
|
||||
@ -878,8 +905,8 @@ template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
|
||||
public:
|
||||
const FunctionT *getFunction() const { return F; }
|
||||
|
||||
void doFunction(const FunctionT *F, const BranchProbabilityInfoT *BPI,
|
||||
const LoopInfoT *LI);
|
||||
void calculate(const FunctionT &F, const BranchProbabilityInfoT &BPI,
|
||||
const LoopInfoT &LI);
|
||||
BlockFrequencyInfoImpl() : BPI(nullptr), LI(nullptr), F(nullptr) {}
|
||||
|
||||
using BlockFrequencyInfoImplBase::getEntryFreq;
|
||||
@ -911,13 +938,13 @@ public:
|
||||
};
|
||||
|
||||
template <class BT>
|
||||
void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
|
||||
const BranchProbabilityInfoT *BPI,
|
||||
const LoopInfoT *LI) {
|
||||
void BlockFrequencyInfoImpl<BT>::calculate(const FunctionT &F,
|
||||
const BranchProbabilityInfoT &BPI,
|
||||
const LoopInfoT &LI) {
|
||||
// Save the parameters.
|
||||
this->BPI = BPI;
|
||||
this->LI = LI;
|
||||
this->F = F;
|
||||
this->BPI = &BPI;
|
||||
this->LI = &LI;
|
||||
this->F = &F;
|
||||
|
||||
// Clean up left-over data structures.
|
||||
BlockFrequencyInfoImplBase::clear();
|
||||
@ -925,8 +952,8 @@ void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
|
||||
Nodes.clear();
|
||||
|
||||
// Initialize.
|
||||
DEBUG(dbgs() << "\nblock-frequency: " << F->getName() << "\n================="
|
||||
<< std::string(F->getName().size(), '=') << "\n");
|
||||
DEBUG(dbgs() << "\nblock-frequency: " << F.getName() << "\n================="
|
||||
<< std::string(F.getName().size(), '=') << "\n");
|
||||
initializeRPOT();
|
||||
initializeLoops();
|
||||
|
||||
@ -1042,6 +1069,8 @@ bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
|
||||
for (const BlockNode &M : Loop.Nodes)
|
||||
if (!propagateMassToSuccessors(&Loop, M))
|
||||
llvm_unreachable("unhandled irreducible control flow");
|
||||
|
||||
adjustLoopHeaderMass(Loop);
|
||||
} else {
|
||||
Working[Loop.getHeader().Index].getMass() = BlockMass::getFull();
|
||||
if (!propagateMassToSuccessors(&Loop, Loop.getHeader()))
|
||||
|
@ -25,9 +25,9 @@ namespace llvm {
|
||||
class LoopInfo;
|
||||
class raw_ostream;
|
||||
|
||||
/// \brief Analysis pass providing branch probability information.
|
||||
/// \brief Analysis providing branch probability information.
|
||||
///
|
||||
/// This is a function analysis pass which provides information on the relative
|
||||
/// This is a function analysis which provides information on the relative
|
||||
/// probabilities of each "edge" in the function's CFG where such an edge is
|
||||
/// defined by a pair (PredBlock and an index in the successors). The
|
||||
/// probability of an edge from one block is always relative to the
|
||||
@ -37,20 +37,14 @@ class raw_ostream;
|
||||
/// identify an edge, since we can have multiple edges from Src to Dst.
|
||||
/// As an example, we can have a switch which jumps to Dst with value 0 and
|
||||
/// value 10.
|
||||
class BranchProbabilityInfo : public FunctionPass {
|
||||
class BranchProbabilityInfo {
|
||||
public:
|
||||
static char ID;
|
||||
BranchProbabilityInfo() {}
|
||||
BranchProbabilityInfo(Function &F, const LoopInfo &LI) { calculate(F, LI); }
|
||||
|
||||
BranchProbabilityInfo() : FunctionPass(ID) {
|
||||
initializeBranchProbabilityInfoPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
void releaseMemory();
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
bool runOnFunction(Function &F) override;
|
||||
|
||||
void releaseMemory() override;
|
||||
|
||||
void print(raw_ostream &OS, const Module *M = nullptr) const override;
|
||||
void print(raw_ostream &OS) const;
|
||||
|
||||
/// \brief Get an edge's probability, relative to other out-edges of the Src.
|
||||
///
|
||||
@ -118,6 +112,8 @@ public:
|
||||
return IsLikely ? (1u << 20) - 1 : 1;
|
||||
}
|
||||
|
||||
void calculate(Function &F, const LoopInfo& LI);
|
||||
|
||||
private:
|
||||
// Since we allow duplicate edges from one basic block to another, we use
|
||||
// a pair (PredBlock and an index in the successors) to specify an edge.
|
||||
@ -133,9 +129,6 @@ private:
|
||||
|
||||
DenseMap<Edge, uint32_t> Weights;
|
||||
|
||||
/// \brief Handle to the LoopInfo analysis.
|
||||
LoopInfo *LI;
|
||||
|
||||
/// \brief Track the last function we run over for printing.
|
||||
Function *LastF;
|
||||
|
||||
@ -152,12 +145,33 @@ private:
|
||||
bool calcMetadataWeights(BasicBlock *BB);
|
||||
bool calcColdCallHeuristics(BasicBlock *BB);
|
||||
bool calcPointerHeuristics(BasicBlock *BB);
|
||||
bool calcLoopBranchHeuristics(BasicBlock *BB);
|
||||
bool calcLoopBranchHeuristics(BasicBlock *BB, const LoopInfo &LI);
|
||||
bool calcZeroHeuristics(BasicBlock *BB);
|
||||
bool calcFloatingPointHeuristics(BasicBlock *BB);
|
||||
bool calcInvokeHeuristics(BasicBlock *BB);
|
||||
};
|
||||
|
||||
/// \brief Legacy analysis pass which computes \c BranchProbabilityInfo.
|
||||
class BranchProbabilityInfoWrapperPass : public FunctionPass {
|
||||
BranchProbabilityInfo BPI;
|
||||
|
||||
public:
|
||||
static char ID;
|
||||
|
||||
BranchProbabilityInfoWrapperPass() : FunctionPass(ID) {
|
||||
initializeBranchProbabilityInfoWrapperPassPass(
|
||||
*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
BranchProbabilityInfo &getBPI() { return BPI; }
|
||||
const BranchProbabilityInfo &getBPI() const { return BPI; }
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
bool runOnFunction(Function &F) override;
|
||||
void releaseMemory() override;
|
||||
void print(raw_ostream &OS, const Module *M = nullptr) const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -78,6 +78,17 @@ bool isPotentiallyReachable(const BasicBlock *From, const BasicBlock *To,
|
||||
const DominatorTree *DT = nullptr,
|
||||
const LoopInfo *LI = nullptr);
|
||||
|
||||
/// \brief Determine whether there is at least one path from a block in
|
||||
/// 'Worklist' to 'StopBB', returning true if uncertain.
|
||||
///
|
||||
/// Determine whether there is a path from at least one block in Worklist to
|
||||
/// StopBB within a single function. Returns false only if we can prove that
|
||||
/// once any block in 'Worklist' has been reached then 'StopBB' can not be
|
||||
/// executed. Conservatively returns true.
|
||||
bool isPotentiallyReachableFromMany(SmallVectorImpl<BasicBlock *> &Worklist,
|
||||
BasicBlock *StopBB,
|
||||
const DominatorTree *DT = nullptr,
|
||||
const LoopInfo *LI = nullptr);
|
||||
} // End llvm namespace
|
||||
|
||||
#endif
|
||||
|
@ -56,6 +56,7 @@
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/IR/CallSite.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/ValueHandle.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include <map>
|
||||
@ -229,7 +230,8 @@ public:
|
||||
/// \brief Adds a function to the list of functions called by this one.
|
||||
void addCalledFunction(CallSite CS, CallGraphNode *M) {
|
||||
assert(!CS.getInstruction() || !CS.getCalledFunction() ||
|
||||
!CS.getCalledFunction()->isIntrinsic());
|
||||
!CS.getCalledFunction()->isIntrinsic() ||
|
||||
!Intrinsic::isLeaf(CS.getCalledFunction()->getIntrinsicID()));
|
||||
CalledFunctions.emplace_back(CS.getInstruction(), M);
|
||||
M->AddRef();
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ namespace llvm {
|
||||
class Use;
|
||||
class Instruction;
|
||||
class DominatorTree;
|
||||
class OrderedBasicBlock;
|
||||
|
||||
/// PointerMayBeCaptured - Return true if this pointer value may be captured
|
||||
/// by the enclosing function (which is required to exist). This routine can
|
||||
@ -41,10 +42,12 @@ namespace llvm {
|
||||
/// it or not. The boolean StoreCaptures specified whether storing the value
|
||||
/// (or part of it) into memory anywhere automatically counts as capturing it
|
||||
/// or not. Captures by the provided instruction are considered if the
|
||||
/// final parameter is true.
|
||||
/// final parameter is true. An ordered basic block in \p OBB could be used
|
||||
/// to speed up capture-tracker queries.
|
||||
bool PointerMayBeCapturedBefore(const Value *V, bool ReturnCaptures,
|
||||
bool StoreCaptures, const Instruction *I,
|
||||
DominatorTree *DT, bool IncludeI = false);
|
||||
DominatorTree *DT, bool IncludeI = false,
|
||||
OrderedBasicBlock *OBB = nullptr);
|
||||
|
||||
/// This callback is used in conjunction with PointerMayBeCaptured. In
|
||||
/// addition to the interface here, you'll need to provide your own getters
|
||||
|
@ -72,6 +72,17 @@ namespace llvm {
|
||||
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
|
||||
ArrayRef<unsigned> Idxs);
|
||||
|
||||
/// \brief Attempt to constant fold an extractvalue instruction with the
|
||||
/// specified operands and indices. The constant result is returned if
|
||||
/// successful; if not, null is returned.
|
||||
Constant *ConstantFoldExtractValueInstruction(Constant *Agg,
|
||||
ArrayRef<unsigned> Idxs);
|
||||
|
||||
/// \brief Attempt to constant fold an extractelement instruction with the
|
||||
/// specified operands and indices. The constant result is returned if
|
||||
/// successful; if not, null is returned.
|
||||
Constant *ConstantFoldExtractElementInstruction(Constant *Val, Constant *Idx);
|
||||
|
||||
/// ConstantFoldLoadFromConstPtr - Return the value that a load from C would
|
||||
/// produce if it is constant and determinable. If this is not determinable,
|
||||
/// return null.
|
||||
|
@ -202,8 +202,8 @@ public:
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class DominanceFrontierBase<BasicBlock>);
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class ForwardDominanceFrontierBase<BasicBlock>);
|
||||
extern template class DominanceFrontierBase<BasicBlock>;
|
||||
extern template class ForwardDominanceFrontierBase<BasicBlock>;
|
||||
|
||||
} // End llvm namespace
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class AssumptionCache;
|
||||
class DominatorTree;
|
||||
class Instruction;
|
||||
class Value;
|
||||
@ -119,15 +120,19 @@ private:
|
||||
class IVUsers : public LoopPass {
|
||||
friend class IVStrideUse;
|
||||
Loop *L;
|
||||
AssumptionCache *AC;
|
||||
LoopInfo *LI;
|
||||
DominatorTree *DT;
|
||||
ScalarEvolution *SE;
|
||||
SmallPtrSet<Instruction*,16> Processed;
|
||||
SmallPtrSet<Instruction*, 16> Processed;
|
||||
|
||||
/// IVUses - A list of all tracked IV uses of induction variable expressions
|
||||
/// we are interested in.
|
||||
ilist<IVStrideUse> IVUses;
|
||||
|
||||
// Ephemeral values used by @llvm.assume in this function.
|
||||
SmallPtrSet<const Value *, 32> EphValues;
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
|
||||
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
||||
|
@ -212,7 +212,7 @@ namespace llvm {
|
||||
/// SimplifyFCmpInst - Given operands for an FCmpInst, see if we can
|
||||
/// fold the result. If not, this returns null.
|
||||
Value *SimplifyFCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const DataLayout &DL,
|
||||
FastMathFlags FMF, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI = nullptr,
|
||||
const DominatorTree *DT = nullptr,
|
||||
AssumptionCache *AC = nullptr,
|
||||
@ -244,6 +244,24 @@ namespace llvm {
|
||||
AssumptionCache *AC = nullptr,
|
||||
const Instruction *CxtI = nullptr);
|
||||
|
||||
/// \brief Given operands for an ExtractValueInst, see if we can fold the
|
||||
/// result. If not, this returns null.
|
||||
Value *SimplifyExtractValueInst(Value *Agg, ArrayRef<unsigned> Idxs,
|
||||
const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI = nullptr,
|
||||
const DominatorTree *DT = nullptr,
|
||||
AssumptionCache *AC = nullptr,
|
||||
const Instruction *CxtI = nullptr);
|
||||
|
||||
/// \brief Given operands for an ExtractElementInst, see if we can fold the
|
||||
/// result. If not, this returns null.
|
||||
Value *SimplifyExtractElementInst(Value *Vec, Value *Idx,
|
||||
const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI = nullptr,
|
||||
const DominatorTree *DT = nullptr,
|
||||
AssumptionCache *AC = nullptr,
|
||||
const Instruction *CxtI = nullptr);
|
||||
|
||||
/// SimplifyTruncInst - Given operands for an TruncInst, see if we can fold
|
||||
/// the result. If not, this returns null.
|
||||
Value *SimplifyTruncInst(Value *Op, Type *Ty, const DataLayout &DL,
|
||||
|
@ -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 */
|
@ -190,7 +190,7 @@ public:
|
||||
|
||||
Function &getFunction() const {
|
||||
return F;
|
||||
};
|
||||
}
|
||||
|
||||
iterator begin() const {
|
||||
return iterator(*G, Callees.begin(), Callees.end());
|
||||
|
@ -25,7 +25,7 @@ namespace llvm {
|
||||
class Instruction;
|
||||
class TargetLibraryInfo;
|
||||
class Value;
|
||||
|
||||
|
||||
/// This pass computes, caches, and vends lazy value constraint information.
|
||||
class LazyValueInfo : public FunctionPass {
|
||||
AssumptionCache *AC;
|
||||
@ -45,23 +45,22 @@ public:
|
||||
enum Tristate {
|
||||
Unknown = -1, False = 0, True = 1
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Public query interface.
|
||||
|
||||
|
||||
/// Determine whether the specified value comparison with a constant is known
|
||||
/// to be true or false on the specified CFG edge.
|
||||
/// Pred is a CmpInst predicate.
|
||||
Tristate getPredicateOnEdge(unsigned Pred, Value *V, Constant *C,
|
||||
BasicBlock *FromBB, BasicBlock *ToBB,
|
||||
Instruction *CxtI = nullptr);
|
||||
|
||||
|
||||
/// Determine whether the specified value comparison with a constant is known
|
||||
/// to be true or false at the specified instruction
|
||||
/// (from an assume intrinsic). Pred is a CmpInst predicate.
|
||||
Tristate getPredicateAt(unsigned Pred, Value *V, Constant *C,
|
||||
Instruction *CxtI);
|
||||
|
||||
|
||||
/// Determine whether the specified value is known to be a
|
||||
/// constant at the end of the specified block. Return null if not.
|
||||
Constant *getConstant(Value *V, BasicBlock *BB, Instruction *CxtI = nullptr);
|
||||
@ -70,14 +69,14 @@ public:
|
||||
/// constant on the specified edge. Return null if not.
|
||||
Constant *getConstantOnEdge(Value *V, BasicBlock *FromBB, BasicBlock *ToBB,
|
||||
Instruction *CxtI = nullptr);
|
||||
|
||||
|
||||
/// Inform the analysis cache that we have threaded an edge from
|
||||
/// PredBB to OldSucc to be from PredBB to NewSucc instead.
|
||||
void threadEdge(BasicBlock *PredBB, BasicBlock *OldSucc, BasicBlock *NewSucc);
|
||||
|
||||
|
||||
/// Inform the analysis cache that we have erased a block.
|
||||
void eraseBlock(BasicBlock *BB);
|
||||
|
||||
|
||||
// Implementation boilerplate.
|
||||
|
||||
void getAnalysisUsage(AnalysisUsage &AU) const override;
|
||||
|
@ -38,11 +38,11 @@ namespace llvm {
|
||||
}
|
||||
~LibCallAliasAnalysis() override;
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS,
|
||||
const Location &Loc) override;
|
||||
|
||||
ModRefResult getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) override {
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc) override;
|
||||
|
||||
ModRefInfo getModRefInfo(ImmutableCallSite CS1,
|
||||
ImmutableCallSite CS2) override {
|
||||
// TODO: Could compare two direct calls against each other if we cared to.
|
||||
return AliasAnalysis::getModRefInfo(CS1, CS2);
|
||||
}
|
||||
@ -62,9 +62,9 @@ namespace llvm {
|
||||
}
|
||||
|
||||
private:
|
||||
ModRefResult AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
|
||||
ImmutableCallSite CS,
|
||||
const Location &Loc);
|
||||
ModRefInfo AnalyzeLibCallDetails(const LibCallFunctionInfo *FI,
|
||||
ImmutableCallSite CS,
|
||||
const MemoryLocation &Loc);
|
||||
};
|
||||
} // End of llvm namespace
|
||||
|
||||
|
@ -48,8 +48,7 @@ class InvokeInst;
|
||||
enum LocResult {
|
||||
Yes, No, Unknown
|
||||
};
|
||||
LocResult (*isLocation)(ImmutableCallSite CS,
|
||||
const AliasAnalysis::Location &Loc);
|
||||
LocResult (*isLocation)(ImmutableCallSite CS, const MemoryLocation &Loc);
|
||||
};
|
||||
|
||||
/// LibCallFunctionInfo - Each record in the array of FunctionInfo structs
|
||||
@ -72,15 +71,15 @@ class InvokeInst;
|
||||
/// any specific context knowledge. For example, if the function is known
|
||||
/// to be readonly, this would be set to 'ref'. If known to be readnone,
|
||||
/// this is set to NoModRef.
|
||||
AliasAnalysis::ModRefResult UniversalBehavior;
|
||||
|
||||
ModRefInfo UniversalBehavior;
|
||||
|
||||
/// LocationMRInfo - This pair captures info about whether a specific
|
||||
/// location is modified or referenced by a libcall.
|
||||
struct LocationMRInfo {
|
||||
/// LocationID - ID # of the accessed location or ~0U for array end.
|
||||
unsigned LocationID;
|
||||
/// MRInfo - Mod/Ref info for this location.
|
||||
AliasAnalysis::ModRefResult MRInfo;
|
||||
ModRefInfo MRInfo;
|
||||
};
|
||||
|
||||
/// DetailsType - Indicate the sense of the LocationDetails array. This
|
||||
@ -207,7 +206,19 @@ class InvokeInst;
|
||||
llvm_unreachable("invalid enum");
|
||||
}
|
||||
|
||||
bool canSimplifyInvokeNoUnwind(const InvokeInst *II);
|
||||
/// \brief Return true if this personality may be safely removed if there
|
||||
/// are no invoke instructions remaining in the current function.
|
||||
inline bool isNoOpWithoutInvoke(EHPersonality Pers) {
|
||||
switch (Pers) {
|
||||
case EHPersonality::Unknown:
|
||||
return false;
|
||||
// All known personalities currently have this behavior
|
||||
default: return true;
|
||||
}
|
||||
llvm_unreachable("invalid enum");
|
||||
}
|
||||
|
||||
bool canSimplifyInvokeNoUnwind(const Function *F);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
|
@ -292,6 +292,163 @@ private:
|
||||
bool couldPreventStoreLoadForward(unsigned Distance, unsigned TypeByteSize);
|
||||
};
|
||||
|
||||
/// \brief Holds information about the memory runtime legality checks to verify
|
||||
/// that a group of pointers do not overlap.
|
||||
class RuntimePointerChecking {
|
||||
public:
|
||||
struct PointerInfo {
|
||||
/// Holds the pointer value that we need to check.
|
||||
TrackingVH<Value> PointerValue;
|
||||
/// Holds the pointer value at the beginning of the loop.
|
||||
const SCEV *Start;
|
||||
/// Holds the pointer value at the end of the loop.
|
||||
const SCEV *End;
|
||||
/// Holds the information if this pointer is used for writing to memory.
|
||||
bool IsWritePtr;
|
||||
/// Holds the id of the set of pointers that could be dependent because of a
|
||||
/// shared underlying object.
|
||||
unsigned DependencySetId;
|
||||
/// Holds the id of the disjoint alias set to which this pointer belongs.
|
||||
unsigned AliasSetId;
|
||||
/// SCEV for the access.
|
||||
const SCEV *Expr;
|
||||
|
||||
PointerInfo(Value *PointerValue, const SCEV *Start, const SCEV *End,
|
||||
bool IsWritePtr, unsigned DependencySetId, unsigned AliasSetId,
|
||||
const SCEV *Expr)
|
||||
: PointerValue(PointerValue), Start(Start), End(End),
|
||||
IsWritePtr(IsWritePtr), DependencySetId(DependencySetId),
|
||||
AliasSetId(AliasSetId), Expr(Expr) {}
|
||||
};
|
||||
|
||||
RuntimePointerChecking(ScalarEvolution *SE) : Need(false), SE(SE) {}
|
||||
|
||||
/// Reset the state of the pointer runtime information.
|
||||
void reset() {
|
||||
Need = false;
|
||||
Pointers.clear();
|
||||
}
|
||||
|
||||
/// Insert a pointer and calculate the start and end SCEVs.
|
||||
void insert(Loop *Lp, Value *Ptr, bool WritePtr, unsigned DepSetId,
|
||||
unsigned ASId, const ValueToValueMap &Strides);
|
||||
|
||||
/// \brief No run-time memory checking is necessary.
|
||||
bool empty() const { return Pointers.empty(); }
|
||||
|
||||
/// A grouping of pointers. A single memcheck is required between
|
||||
/// two groups.
|
||||
struct CheckingPtrGroup {
|
||||
/// \brief Create a new pointer checking group containing a single
|
||||
/// pointer, with index \p Index in RtCheck.
|
||||
CheckingPtrGroup(unsigned Index, RuntimePointerChecking &RtCheck)
|
||||
: RtCheck(RtCheck), High(RtCheck.Pointers[Index].End),
|
||||
Low(RtCheck.Pointers[Index].Start) {
|
||||
Members.push_back(Index);
|
||||
}
|
||||
|
||||
/// \brief Tries to add the pointer recorded in RtCheck at index
|
||||
/// \p Index to this pointer checking group. We can only add a pointer
|
||||
/// to a checking group if we will still be able to get
|
||||
/// the upper and lower bounds of the check. Returns true in case
|
||||
/// of success, false otherwise.
|
||||
bool addPointer(unsigned Index);
|
||||
|
||||
/// Constitutes the context of this pointer checking group. For each
|
||||
/// pointer that is a member of this group we will retain the index
|
||||
/// at which it appears in RtCheck.
|
||||
RuntimePointerChecking &RtCheck;
|
||||
/// The SCEV expression which represents the upper bound of all the
|
||||
/// pointers in this group.
|
||||
const SCEV *High;
|
||||
/// The SCEV expression which represents the lower bound of all the
|
||||
/// pointers in this group.
|
||||
const SCEV *Low;
|
||||
/// Indices of all the pointers that constitute this grouping.
|
||||
SmallVector<unsigned, 2> Members;
|
||||
};
|
||||
|
||||
/// \brief A memcheck which made up of a pair of grouped pointers.
|
||||
///
|
||||
/// These *have* to be const for now, since checks are generated from
|
||||
/// CheckingPtrGroups in LAI::addRuntimeCheck which is a const member
|
||||
/// function. FIXME: once check-generation is moved inside this class (after
|
||||
/// the PtrPartition hack is removed), we could drop const.
|
||||
typedef std::pair<const CheckingPtrGroup *, const CheckingPtrGroup *>
|
||||
PointerCheck;
|
||||
|
||||
/// \brief Groups pointers such that a single memcheck is required
|
||||
/// between two different groups. This will clear the CheckingGroups vector
|
||||
/// and re-compute it. We will only group dependecies if \p UseDependencies
|
||||
/// is true, otherwise we will create a separate group for each pointer.
|
||||
void groupChecks(MemoryDepChecker::DepCandidates &DepCands,
|
||||
bool UseDependencies);
|
||||
|
||||
/// Generate the checks and return them.
|
||||
///
|
||||
/// \p PtrToPartition contains the partition number for pointers. If passed,
|
||||
/// omit checks between pointers belonging to the same partition. Partition
|
||||
/// number -1 means that the pointer is used in multiple partitions. In this
|
||||
/// case we can't safely omit the check.
|
||||
SmallVector<PointerCheck, 4>
|
||||
generateChecks(const SmallVectorImpl<int> *PtrPartition = nullptr) const;
|
||||
|
||||
/// \brief Decide if we need to add a check between two groups of pointers,
|
||||
/// according to needsChecking.
|
||||
bool needsChecking(const CheckingPtrGroup &M, const CheckingPtrGroup &N,
|
||||
const SmallVectorImpl<int> *PtrPartition) const;
|
||||
|
||||
/// \brief Return true if any pointer requires run-time checking according
|
||||
/// to needsChecking.
|
||||
bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
|
||||
|
||||
/// \brief Returns the number of run-time checks required according to
|
||||
/// needsChecking.
|
||||
unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const;
|
||||
|
||||
/// \brief Print the list run-time memory checks necessary.
|
||||
///
|
||||
/// If \p PtrPartition is set, it contains the partition number for
|
||||
/// pointers (-1 if the pointer belongs to multiple partitions). In this
|
||||
/// case omit checks between pointers belonging to the same partition.
|
||||
void print(raw_ostream &OS, unsigned Depth = 0,
|
||||
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
|
||||
|
||||
/// Print \p Checks.
|
||||
void printChecks(raw_ostream &OS, const SmallVectorImpl<PointerCheck> &Checks,
|
||||
unsigned Depth = 0) const;
|
||||
|
||||
/// This flag indicates if we need to add the runtime check.
|
||||
bool Need;
|
||||
|
||||
/// Information about the pointers that may require checking.
|
||||
SmallVector<PointerInfo, 2> Pointers;
|
||||
|
||||
/// Holds a partitioning of pointers into "check groups".
|
||||
SmallVector<CheckingPtrGroup, 2> CheckingGroups;
|
||||
|
||||
/// \brief Check if pointers are in the same partition
|
||||
///
|
||||
/// \p PtrToPartition contains the partition number for pointers (-1 if the
|
||||
/// pointer belongs to multiple partitions).
|
||||
static bool
|
||||
arePointersInSamePartition(const SmallVectorImpl<int> &PtrToPartition,
|
||||
unsigned PtrIdx1, unsigned PtrIdx2);
|
||||
|
||||
/// \brief Decide whether we need to issue a run-time check for pointer at
|
||||
/// index \p I and \p J to prove their independence.
|
||||
///
|
||||
/// If \p PtrPartition is set, it contains the partition number for
|
||||
/// pointers (-1 if the pointer belongs to multiple partitions). In this
|
||||
/// case omit checks between pointers belonging to the same partition.
|
||||
bool needsChecking(unsigned I, unsigned J,
|
||||
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
|
||||
|
||||
private:
|
||||
/// Holds a pointer to the ScalarEvolution analysis.
|
||||
ScalarEvolution *SE;
|
||||
};
|
||||
|
||||
/// \brief Drive the analysis of memory accesses in the loop
|
||||
///
|
||||
/// This class is responsible for analyzing the memory accesses of a loop. It
|
||||
@ -308,72 +465,6 @@ private:
|
||||
/// RuntimePointerCheck class.
|
||||
class LoopAccessInfo {
|
||||
public:
|
||||
/// This struct holds information about the memory runtime legality check that
|
||||
/// a group of pointers do not overlap.
|
||||
struct RuntimePointerCheck {
|
||||
RuntimePointerCheck() : Need(false) {}
|
||||
|
||||
/// Reset the state of the pointer runtime information.
|
||||
void reset() {
|
||||
Need = false;
|
||||
Pointers.clear();
|
||||
Starts.clear();
|
||||
Ends.clear();
|
||||
IsWritePtr.clear();
|
||||
DependencySetId.clear();
|
||||
AliasSetId.clear();
|
||||
}
|
||||
|
||||
/// Insert a pointer and calculate the start and end SCEVs.
|
||||
void insert(ScalarEvolution *SE, Loop *Lp, Value *Ptr, bool WritePtr,
|
||||
unsigned DepSetId, unsigned ASId,
|
||||
const ValueToValueMap &Strides);
|
||||
|
||||
/// \brief No run-time memory checking is necessary.
|
||||
bool empty() const { return Pointers.empty(); }
|
||||
|
||||
/// \brief Decide whether we need to issue a run-time check for pointer at
|
||||
/// index \p I and \p J to prove their independence.
|
||||
///
|
||||
/// If \p PtrPartition is set, it contains the partition number for
|
||||
/// pointers (-1 if the pointer belongs to multiple partitions). In this
|
||||
/// case omit checks between pointers belonging to the same partition.
|
||||
bool needsChecking(unsigned I, unsigned J,
|
||||
const SmallVectorImpl<int> *PtrPartition) const;
|
||||
|
||||
/// \brief Return true if any pointer requires run-time checking according
|
||||
/// to needsChecking.
|
||||
bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const;
|
||||
|
||||
/// \brief Returns the number of run-time checks required according to
|
||||
/// needsChecking.
|
||||
unsigned getNumberOfChecks(const SmallVectorImpl<int> *PtrPartition) const;
|
||||
|
||||
/// \brief Print the list run-time memory checks necessary.
|
||||
///
|
||||
/// If \p PtrPartition is set, it contains the partition number for
|
||||
/// pointers (-1 if the pointer belongs to multiple partitions). In this
|
||||
/// case omit checks between pointers belonging to the same partition.
|
||||
void print(raw_ostream &OS, unsigned Depth = 0,
|
||||
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
|
||||
|
||||
/// This flag indicates if we need to add the runtime check.
|
||||
bool Need;
|
||||
/// Holds the pointers that we need to check.
|
||||
SmallVector<TrackingVH<Value>, 2> Pointers;
|
||||
/// Holds the pointer value at the beginning of the loop.
|
||||
SmallVector<const SCEV*, 2> Starts;
|
||||
/// Holds the pointer value at the end of the loop.
|
||||
SmallVector<const SCEV*, 2> Ends;
|
||||
/// Holds the information if this pointer is used for writing to memory.
|
||||
SmallVector<bool, 2> IsWritePtr;
|
||||
/// Holds the id of the set of pointers that could be dependent because of a
|
||||
/// shared underlying object.
|
||||
SmallVector<unsigned, 2> DependencySetId;
|
||||
/// Holds the id of the disjoint alias set to which this pointer belongs.
|
||||
SmallVector<unsigned, 2> AliasSetId;
|
||||
};
|
||||
|
||||
LoopAccessInfo(Loop *L, ScalarEvolution *SE, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI, AliasAnalysis *AA,
|
||||
DominatorTree *DT, LoopInfo *LI,
|
||||
@ -383,15 +474,15 @@ public:
|
||||
/// no memory dependence cycles.
|
||||
bool canVectorizeMemory() const { return CanVecMem; }
|
||||
|
||||
const RuntimePointerCheck *getRuntimePointerCheck() const {
|
||||
return &PtrRtCheck;
|
||||
const RuntimePointerChecking *getRuntimePointerChecking() const {
|
||||
return &PtrRtChecking;
|
||||
}
|
||||
|
||||
/// \brief Number of memchecks required to prove independence of otherwise
|
||||
/// may-alias pointers.
|
||||
unsigned getNumRuntimePointerChecks(
|
||||
const SmallVectorImpl<int> *PtrPartition = nullptr) const {
|
||||
return PtrRtCheck.getNumberOfChecks(PtrPartition);
|
||||
return PtrRtChecking.getNumberOfChecks(PtrPartition);
|
||||
}
|
||||
|
||||
/// Return true if the block BB needs to be predicated in order for the loop
|
||||
@ -419,6 +510,16 @@ public:
|
||||
addRuntimeCheck(Instruction *Loc,
|
||||
const SmallVectorImpl<int> *PtrPartition = nullptr) const;
|
||||
|
||||
/// \brief Generete the instructions for the checks in \p PointerChecks.
|
||||
///
|
||||
/// Returns a pair of instructions where the first element is the first
|
||||
/// instruction generated in possibly a sequence of instructions and the
|
||||
/// second value is the final comparator value or NULL if no check is needed.
|
||||
std::pair<Instruction *, Instruction *>
|
||||
addRuntimeCheck(Instruction *Loc,
|
||||
const SmallVectorImpl<RuntimePointerChecking::PointerCheck>
|
||||
&PointerChecks) const;
|
||||
|
||||
/// \brief The diagnostics report generated for the analysis. E.g. why we
|
||||
/// couldn't analyze the loop.
|
||||
const Optional<LoopAccessReport> &getReport() const { return Report; }
|
||||
@ -461,7 +562,7 @@ private:
|
||||
|
||||
/// We need to check that all of the pointers in this list are disjoint
|
||||
/// at runtime.
|
||||
RuntimePointerCheck PtrRtCheck;
|
||||
RuntimePointerChecking PtrRtChecking;
|
||||
|
||||
/// \brief the Memory Dependence Checker which can determine the
|
||||
/// loop-independent and loop-carried dependences between memory accesses.
|
||||
|
@ -347,9 +347,7 @@ raw_ostream& operator<<(raw_ostream &OS, const LoopBase<BlockT, LoopT> &Loop) {
|
||||
}
|
||||
|
||||
// Implementation in LoopInfoImpl.h
|
||||
#ifdef __GNUC__
|
||||
__extension__ extern template class LoopBase<BasicBlock, Loop>;
|
||||
#endif
|
||||
extern template class LoopBase<BasicBlock, Loop>;
|
||||
|
||||
class Loop : public LoopBase<BasicBlock, Loop> {
|
||||
public:
|
||||
@ -624,7 +622,7 @@ public:
|
||||
}
|
||||
|
||||
/// Create the loop forest using a stable algorithm.
|
||||
void Analyze(DominatorTreeBase<BlockT> &DomTree);
|
||||
void analyze(const DominatorTreeBase<BlockT> &DomTree);
|
||||
|
||||
// Debugging
|
||||
void print(raw_ostream &OS) const;
|
||||
@ -633,9 +631,7 @@ public:
|
||||
};
|
||||
|
||||
// Implementation in LoopInfoImpl.h
|
||||
#ifdef __GNUC__
|
||||
__extension__ extern template class LoopInfoBase<BasicBlock, Loop>;
|
||||
#endif
|
||||
extern template class LoopInfoBase<BasicBlock, Loop>;
|
||||
|
||||
class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
|
||||
typedef LoopInfoBase<BasicBlock, Loop> BaseT;
|
||||
@ -646,6 +642,7 @@ class LoopInfo : public LoopInfoBase<BasicBlock, Loop> {
|
||||
LoopInfo(const LoopInfo &) = delete;
|
||||
public:
|
||||
LoopInfo() {}
|
||||
explicit LoopInfo(const DominatorTreeBase<BasicBlock> &DomTree);
|
||||
|
||||
LoopInfo(LoopInfo &&Arg) : BaseT(std::move(static_cast<BaseT &>(Arg))) {}
|
||||
LoopInfo &operator=(LoopInfo &&RHS) {
|
||||
|
@ -345,7 +345,7 @@ void LoopBase<BlockT, LoopT>::print(raw_ostream &OS, unsigned Depth) const {
|
||||
template<class BlockT, class LoopT>
|
||||
static void discoverAndMapSubloop(LoopT *L, ArrayRef<BlockT*> Backedges,
|
||||
LoopInfoBase<BlockT, LoopT> *LI,
|
||||
DominatorTreeBase<BlockT> &DomTree) {
|
||||
const DominatorTreeBase<BlockT> &DomTree) {
|
||||
typedef GraphTraits<Inverse<BlockT*> > InvBlockTraits;
|
||||
|
||||
unsigned NumBlocks = 0;
|
||||
@ -468,10 +468,10 @@ void PopulateLoopsDFS<BlockT, LoopT>::insertIntoLoop(BlockT *Block) {
|
||||
/// insertions per block.
|
||||
template<class BlockT, class LoopT>
|
||||
void LoopInfoBase<BlockT, LoopT>::
|
||||
Analyze(DominatorTreeBase<BlockT> &DomTree) {
|
||||
analyze(const DominatorTreeBase<BlockT> &DomTree) {
|
||||
|
||||
// Postorder traversal of the dominator tree.
|
||||
DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode();
|
||||
const DomTreeNodeBase<BlockT> *DomRoot = DomTree.getRootNode();
|
||||
for (auto DomNode : post_order(DomRoot)) {
|
||||
|
||||
BlockT *Header = DomNode->getBlock();
|
||||
|
@ -287,7 +287,7 @@ namespace llvm {
|
||||
/// conflicting tags.
|
||||
AAMDNodes AATags;
|
||||
|
||||
NonLocalPointerInfo() : Size(AliasAnalysis::UnknownSize) {}
|
||||
NonLocalPointerInfo() : Size(MemoryLocation::UnknownSize) {}
|
||||
};
|
||||
|
||||
/// CachedNonLocalPointerInfo - This map stores the cached results of doing
|
||||
@ -403,13 +403,12 @@ namespace llvm {
|
||||
///
|
||||
/// Note that this is an uncached query, and thus may be inefficient.
|
||||
///
|
||||
MemDepResult getPointerDependencyFrom(const AliasAnalysis::Location &Loc,
|
||||
MemDepResult getPointerDependencyFrom(const MemoryLocation &Loc,
|
||||
bool isLoad,
|
||||
BasicBlock::iterator ScanIt,
|
||||
BasicBlock *BB,
|
||||
Instruction *QueryInst = nullptr);
|
||||
|
||||
|
||||
/// getLoadLoadClobberFullWidthSize - This is a little bit of analysis that
|
||||
/// looks at a memory location for a load (specified by MemLocBase, Offs,
|
||||
/// and Size) and compares it against a load. If the specified load could
|
||||
@ -428,15 +427,14 @@ namespace llvm {
|
||||
BasicBlock *BB);
|
||||
bool getNonLocalPointerDepFromBB(Instruction *QueryInst,
|
||||
const PHITransAddr &Pointer,
|
||||
const AliasAnalysis::Location &Loc,
|
||||
bool isLoad, BasicBlock *BB,
|
||||
const MemoryLocation &Loc, bool isLoad,
|
||||
BasicBlock *BB,
|
||||
SmallVectorImpl<NonLocalDepResult> &Result,
|
||||
DenseMap<BasicBlock*, Value*> &Visited,
|
||||
DenseMap<BasicBlock *, Value *> &Visited,
|
||||
bool SkipFirstBlock = false);
|
||||
MemDepResult GetNonLocalInfoForBlock(Instruction *QueryInst,
|
||||
const AliasAnalysis::Location &Loc,
|
||||
bool isLoad, BasicBlock *BB,
|
||||
NonLocalDepInfo *Cache,
|
||||
const MemoryLocation &Loc, bool isLoad,
|
||||
BasicBlock *BB, NonLocalDepInfo *Cache,
|
||||
unsigned NumSortedEntries);
|
||||
|
||||
void RemoveCachedNonLocalPointerDependencies(ValueIsLoadPair P);
|
||||
|
@ -26,6 +26,7 @@ class LoadInst;
|
||||
class StoreInst;
|
||||
class MemTransferInst;
|
||||
class MemIntrinsic;
|
||||
class TargetLibraryInfo;
|
||||
|
||||
/// Representation for a specific memory location.
|
||||
///
|
||||
@ -87,6 +88,10 @@ public:
|
||||
/// transfer.
|
||||
static MemoryLocation getForDest(const MemIntrinsic *MI);
|
||||
|
||||
/// Return a location representing a particular argument of a call.
|
||||
static MemoryLocation getForArgument(ImmutableCallSite CS, unsigned ArgIdx,
|
||||
const TargetLibraryInfo &TLI);
|
||||
|
||||
explicit MemoryLocation(const Value *Ptr = nullptr,
|
||||
uint64_t Size = UnknownSize,
|
||||
const AAMDNodes &AATags = AAMDNodes())
|
||||
|
66
include/llvm/Analysis/OrderedBasicBlock.h
Normal file
66
include/llvm/Analysis/OrderedBasicBlock.h
Normal 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
|
@ -902,9 +902,9 @@ inline raw_ostream &operator<<(raw_ostream &OS,
|
||||
return OS << Node.template getNodeAs<BlockT>()->getName();
|
||||
}
|
||||
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class RegionBase<RegionTraits<Function>>);
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class RegionNodeBase<RegionTraits<Function>>);
|
||||
EXTERN_TEMPLATE_INSTANTIATION(class RegionInfoBase<RegionTraits<Function>>);
|
||||
extern template class RegionBase<RegionTraits<Function>>;
|
||||
extern template class RegionNodeBase<RegionTraits<Function>>;
|
||||
extern template class RegionInfoBase<RegionTraits<Function>>;
|
||||
|
||||
} // End llvm namespace
|
||||
#endif
|
||||
|
@ -48,6 +48,7 @@ namespace llvm {
|
||||
class LoopInfo;
|
||||
class Operator;
|
||||
class SCEVUnknown;
|
||||
class SCEVAddRecExpr;
|
||||
class SCEV;
|
||||
template<> struct FoldingSetTrait<SCEV>;
|
||||
|
||||
@ -565,19 +566,43 @@ namespace llvm {
|
||||
/// forgetMemoizedResults - Drop memoized information computed for S.
|
||||
void forgetMemoizedResults(const SCEV *S);
|
||||
|
||||
/// Return an existing SCEV for V if there is one, otherwise return nullptr.
|
||||
const SCEV *getExistingSCEV(Value *V);
|
||||
|
||||
/// Return false iff given SCEV contains a SCEVUnknown with NULL value-
|
||||
/// pointer.
|
||||
bool checkValidity(const SCEV *S) const;
|
||||
|
||||
// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be equal
|
||||
// to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is equivalent to
|
||||
// proving no signed (resp. unsigned) wrap in {`Start`,+,`Step`} if
|
||||
// `ExtendOpTy` is `SCEVSignExtendExpr` (resp. `SCEVZeroExtendExpr`).
|
||||
//
|
||||
/// Return true if `ExtendOpTy`({`Start`,+,`Step`}) can be proved to be
|
||||
/// equal to {`ExtendOpTy`(`Start`),+,`ExtendOpTy`(`Step`)}. This is
|
||||
/// equivalent to proving no signed (resp. unsigned) wrap in
|
||||
/// {`Start`,+,`Step`} if `ExtendOpTy` is `SCEVSignExtendExpr`
|
||||
/// (resp. `SCEVZeroExtendExpr`).
|
||||
///
|
||||
template<typename ExtendOpTy>
|
||||
bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
|
||||
const Loop *L);
|
||||
|
||||
bool isMonotonicPredicateImpl(const SCEVAddRecExpr *LHS,
|
||||
ICmpInst::Predicate Pred, bool &Increasing);
|
||||
|
||||
/// Return true if, for all loop invariant X, the predicate "LHS `Pred` X"
|
||||
/// is monotonically increasing or decreasing. In the former case set
|
||||
/// `Increasing` to true and in the latter case set `Increasing` to false.
|
||||
///
|
||||
/// A predicate is said to be monotonically increasing if may go from being
|
||||
/// false to being true as the loop iterates, but never the other way
|
||||
/// around. A predicate is said to be monotonically decreasing if may go
|
||||
/// from being true to being false as the loop iterates, but never the other
|
||||
/// way around.
|
||||
bool isMonotonicPredicate(const SCEVAddRecExpr *LHS,
|
||||
ICmpInst::Predicate Pred, bool &Increasing);
|
||||
|
||||
// Return SCEV no-wrap flags that can be proven based on reasoning
|
||||
// about how poison produced from no-wrap flags on this value
|
||||
// (e.g. a nuw add) would trigger undefined behavior on overflow.
|
||||
SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V);
|
||||
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
ScalarEvolution();
|
||||
@ -899,6 +924,16 @@ namespace llvm {
|
||||
bool isKnownPredicate(ICmpInst::Predicate Pred,
|
||||
const SCEV *LHS, const SCEV *RHS);
|
||||
|
||||
/// Return true if the result of the predicate LHS `Pred` RHS is loop
|
||||
/// invariant with respect to L. Set InvariantPred, InvariantLHS and
|
||||
/// InvariantLHS so that InvariantLHS `InvariantPred` InvariantRHS is the
|
||||
/// loop invariant form of LHS `Pred` RHS.
|
||||
bool isLoopInvariantPredicate(ICmpInst::Predicate Pred, const SCEV *LHS,
|
||||
const SCEV *RHS, const Loop *L,
|
||||
ICmpInst::Predicate &InvariantPred,
|
||||
const SCEV *&InvariantLHS,
|
||||
const SCEV *&InvariantRHS);
|
||||
|
||||
/// SimplifyICmpOperands - Simplify LHS and RHS in a comparison with
|
||||
/// predicate Pred. Return true iff any changes were made. If the
|
||||
/// operands are provably equal or unequal, LHS and RHS are set to
|
||||
@ -954,6 +989,86 @@ namespace llvm {
|
||||
void print(raw_ostream &OS, const Module* = nullptr) const override;
|
||||
void verifyAnalysis() const override;
|
||||
|
||||
/// Collect parametric terms occurring in step expressions.
|
||||
void collectParametricTerms(const SCEV *Expr,
|
||||
SmallVectorImpl<const SCEV *> &Terms);
|
||||
|
||||
|
||||
|
||||
/// Return in Subscripts the access functions for each dimension in Sizes.
|
||||
void computeAccessFunctions(const SCEV *Expr,
|
||||
SmallVectorImpl<const SCEV *> &Subscripts,
|
||||
SmallVectorImpl<const SCEV *> &Sizes);
|
||||
|
||||
/// Split this SCEVAddRecExpr into two vectors of SCEVs representing the
|
||||
/// subscripts and sizes of an array access.
|
||||
///
|
||||
/// The delinearization is a 3 step process: the first two steps compute the
|
||||
/// sizes of each subscript and the third step computes the access functions
|
||||
/// for the delinearized array:
|
||||
///
|
||||
/// 1. Find the terms in the step functions
|
||||
/// 2. Compute the array size
|
||||
/// 3. Compute the access function: divide the SCEV by the array size
|
||||
/// starting with the innermost dimensions found in step 2. The Quotient
|
||||
/// is the SCEV to be divided in the next step of the recursion. The
|
||||
/// Remainder is the subscript of the innermost dimension. Loop over all
|
||||
/// array dimensions computed in step 2.
|
||||
///
|
||||
/// To compute a uniform array size for several memory accesses to the same
|
||||
/// object, one can collect in step 1 all the step terms for all the memory
|
||||
/// accesses, and compute in step 2 a unique array shape. This guarantees
|
||||
/// that the array shape will be the same across all memory accesses.
|
||||
///
|
||||
/// FIXME: We could derive the result of steps 1 and 2 from a description of
|
||||
/// the array shape given in metadata.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// A[][n][m]
|
||||
///
|
||||
/// for i
|
||||
/// for j
|
||||
/// for k
|
||||
/// A[j+k][2i][5i] =
|
||||
///
|
||||
/// The initial SCEV:
|
||||
///
|
||||
/// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k]
|
||||
///
|
||||
/// 1. Find the different terms in the step functions:
|
||||
/// -> [2*m, 5, n*m, n*m]
|
||||
///
|
||||
/// 2. Compute the array size: sort and unique them
|
||||
/// -> [n*m, 2*m, 5]
|
||||
/// find the GCD of all the terms = 1
|
||||
/// divide by the GCD and erase constant terms
|
||||
/// -> [n*m, 2*m]
|
||||
/// GCD = m
|
||||
/// divide by GCD -> [n, 2]
|
||||
/// remove constant terms
|
||||
/// -> [n]
|
||||
/// size of the array is A[unknown][n][m]
|
||||
///
|
||||
/// 3. Compute the access function
|
||||
/// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m
|
||||
/// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k
|
||||
/// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k
|
||||
/// The remainder is the subscript of the innermost array dimension: [5i].
|
||||
///
|
||||
/// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n
|
||||
/// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k
|
||||
/// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k
|
||||
/// The Remainder is the subscript of the next array dimension: [2i].
|
||||
///
|
||||
/// The subscript of the outermost dimension is the Quotient: [j+k].
|
||||
///
|
||||
/// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i].
|
||||
void delinearize(const SCEV *Expr,
|
||||
SmallVectorImpl<const SCEV *> &Subscripts,
|
||||
SmallVectorImpl<const SCEV *> &Sizes,
|
||||
const SCEV *ElementSize);
|
||||
|
||||
private:
|
||||
/// Compute the backedge taken count knowing the interval difference, the
|
||||
/// stride and presence of the equality in the comparison.
|
||||
|
@ -356,84 +356,6 @@ namespace llvm {
|
||||
static inline bool classof(const SCEV *S) {
|
||||
return S->getSCEVType() == scAddRecExpr;
|
||||
}
|
||||
|
||||
/// Collect parametric terms occurring in step expressions.
|
||||
void collectParametricTerms(ScalarEvolution &SE,
|
||||
SmallVectorImpl<const SCEV *> &Terms) const;
|
||||
|
||||
/// Return in Subscripts the access functions for each dimension in Sizes.
|
||||
void computeAccessFunctions(ScalarEvolution &SE,
|
||||
SmallVectorImpl<const SCEV *> &Subscripts,
|
||||
SmallVectorImpl<const SCEV *> &Sizes) const;
|
||||
|
||||
/// Split this SCEVAddRecExpr into two vectors of SCEVs representing the
|
||||
/// subscripts and sizes of an array access.
|
||||
///
|
||||
/// The delinearization is a 3 step process: the first two steps compute the
|
||||
/// sizes of each subscript and the third step computes the access functions
|
||||
/// for the delinearized array:
|
||||
///
|
||||
/// 1. Find the terms in the step functions
|
||||
/// 2. Compute the array size
|
||||
/// 3. Compute the access function: divide the SCEV by the array size
|
||||
/// starting with the innermost dimensions found in step 2. The Quotient
|
||||
/// is the SCEV to be divided in the next step of the recursion. The
|
||||
/// Remainder is the subscript of the innermost dimension. Loop over all
|
||||
/// array dimensions computed in step 2.
|
||||
///
|
||||
/// To compute a uniform array size for several memory accesses to the same
|
||||
/// object, one can collect in step 1 all the step terms for all the memory
|
||||
/// accesses, and compute in step 2 a unique array shape. This guarantees
|
||||
/// that the array shape will be the same across all memory accesses.
|
||||
///
|
||||
/// FIXME: We could derive the result of steps 1 and 2 from a description of
|
||||
/// the array shape given in metadata.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// A[][n][m]
|
||||
///
|
||||
/// for i
|
||||
/// for j
|
||||
/// for k
|
||||
/// A[j+k][2i][5i] =
|
||||
///
|
||||
/// The initial SCEV:
|
||||
///
|
||||
/// A[{{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k]
|
||||
///
|
||||
/// 1. Find the different terms in the step functions:
|
||||
/// -> [2*m, 5, n*m, n*m]
|
||||
///
|
||||
/// 2. Compute the array size: sort and unique them
|
||||
/// -> [n*m, 2*m, 5]
|
||||
/// find the GCD of all the terms = 1
|
||||
/// divide by the GCD and erase constant terms
|
||||
/// -> [n*m, 2*m]
|
||||
/// GCD = m
|
||||
/// divide by GCD -> [n, 2]
|
||||
/// remove constant terms
|
||||
/// -> [n]
|
||||
/// size of the array is A[unknown][n][m]
|
||||
///
|
||||
/// 3. Compute the access function
|
||||
/// a. Divide {{{0,+,2*m+5}_i, +, n*m}_j, +, n*m}_k by the innermost size m
|
||||
/// Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k
|
||||
/// Remainder: {{{0,+,5}_i, +, 0}_j, +, 0}_k
|
||||
/// The remainder is the subscript of the innermost array dimension: [5i].
|
||||
///
|
||||
/// b. Divide Quotient: {{{0,+,2}_i, +, n}_j, +, n}_k by next outer size n
|
||||
/// Quotient: {{{0,+,0}_i, +, 1}_j, +, 1}_k
|
||||
/// Remainder: {{{0,+,2}_i, +, 0}_j, +, 0}_k
|
||||
/// The Remainder is the subscript of the next array dimension: [2i].
|
||||
///
|
||||
/// The subscript of the outermost dimension is the Quotient: [j+k].
|
||||
///
|
||||
/// Overall, we have: A[][n][m], and the access function: A[j+k][2i][5i].
|
||||
void delinearize(ScalarEvolution &SE,
|
||||
SmallVectorImpl<const SCEV *> &Subscripts,
|
||||
SmallVectorImpl<const SCEV *> &Sizes,
|
||||
const SCEV *ElementSize) const;
|
||||
};
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user